mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 08:56:36 +02:00
Merge branch 'MDL-67075-redis-session-locks' of https://github.com/brendanheywood/moodle
This commit is contained in:
commit
e217c0f326
1 changed files with 33 additions and 13 deletions
|
@ -339,7 +339,7 @@ class redis extends handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a session lock so we are the only one using it at the moent.
|
* Obtain a session lock so we are the only one using it at the moment.
|
||||||
*
|
*
|
||||||
* @param string $id The session id to lock.
|
* @param string $id The session id to lock.
|
||||||
* @return bool true when session was locked, exception otherwise.
|
* @return bool true when session was locked, exception otherwise.
|
||||||
|
@ -355,23 +355,43 @@ class redis extends handler {
|
||||||
* on the session for the entire time it is open. If another AJAX call, or page is using
|
* on the session for the entire time it is open. If another AJAX call, or page is using
|
||||||
* the session then we just wait until it finishes before we can open the session.
|
* the session then we just wait until it finishes before we can open the session.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Store the current host, process id and the request URI so it's easy to track who has the lock.
|
||||||
|
$hostname = gethostname();
|
||||||
|
if ($hostname === false) {
|
||||||
|
$hostname = 'UNKNOWN HOST';
|
||||||
|
}
|
||||||
|
$pid = getmypid();
|
||||||
|
if ($pid === false) {
|
||||||
|
$pid = 'UNKNOWN';
|
||||||
|
}
|
||||||
|
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'unknown uri';
|
||||||
|
|
||||||
|
$whoami = "[pid {$pid}] {$hostname}:$uri";
|
||||||
|
|
||||||
while (!$haslock) {
|
while (!$haslock) {
|
||||||
$haslock = $this->connection->setnx($lockkey, '1');
|
|
||||||
if (!$haslock) {
|
$haslock = $this->connection->setnx($lockkey, $whoami);
|
||||||
usleep(rand(100000, 1000000));
|
|
||||||
if ($this->time() > $startlocktime + $this->acquiretimeout) {
|
if ($haslock) {
|
||||||
// This is a fatal error, better inform users.
|
|
||||||
// It should not happen very often - all pages that need long time to execute
|
|
||||||
// should close session immediately after access control checks.
|
|
||||||
error_log('Cannot obtain session lock for sid: '.$id.' within '.$this->acquiretimeout.
|
|
||||||
'. It is likely another page has a long session lock, or the session lock was never released.');
|
|
||||||
throw new exception("Unable to obtain session lock");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->locks[$id] = $this->time() + $this->lockexpire;
|
$this->locks[$id] = $this->time() + $this->lockexpire;
|
||||||
$this->connection->expire($lockkey, $this->lockexpire);
|
$this->connection->expire($lockkey, $this->lockexpire);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->time() > $startlocktime + $this->acquiretimeout) {
|
||||||
|
// This is a fatal error, better inform users.
|
||||||
|
// It should not happen very often - all pages that need long time to execute
|
||||||
|
// should close session immediately after access control checks.
|
||||||
|
$whohaslock = $this->connection->get($lockkey);
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
error_log("Cannot obtain session lock for sid: $id within $this->acquiretimeout seconds. " .
|
||||||
|
"It is likely another page ($whohaslock) has a long session lock, or the session lock was never released.");
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
throw new exception("Unable to obtain session lock");
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(rand(100000, 1000000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue