Skip to content

Commit

Permalink
address issue #1: spinlock should usleep
Browse files Browse the repository at this point in the history
  • Loading branch information
1ma committed Feb 5, 2017
1 parent 0ac53e0 commit 50ec3fa
Showing 1 changed file with 24 additions and 4 deletions.
28 changes: 24 additions & 4 deletions RedisSessionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
*/
class RedisSessionHandler extends \SessionHandler
{
/**
* Wait time (1ms) after first locking attempt. It doubles
* for every unsuccessful retry until it either reaches
* MAX_WAIT_TIME or succeeds.
*/
const MIN_WAIT_TIME = 1000;

/**
* Maximum wait time (128ms) between locking attempts.
*/
const MAX_WAIT_TIME = 128000;

/**
* @var \Redis
*/
Expand Down Expand Up @@ -161,7 +173,15 @@ public function gc($maxlifetime)
*/
private function acquireLockOn($session_id)
{
while (false === $this->redis->set("{$session_id}_lock", '', ['nx', 'ex' => $this->lock_ttl]));
$wait = self::MIN_WAIT_TIME;

while (false === $this->redis->set("{$session_id}_lock", '', ['nx', 'ex' => $this->lock_ttl])) {
usleep($wait);

if (self::MAX_WAIT_TIME > $wait) {
$wait *= 2;
}
}

$this->open_sessions[] = $session_id;
}
Expand All @@ -179,9 +199,9 @@ private function releaseLocks()
* A session ID must be regenerated when it came from the HTTP
* request and can not be found in Redis.
*
* When that happens it either means that an old session expired in Redis
* but not in the browser, or a malicious client is trying to pull off
* a session fixation attack.
* When that happens it either means that old session data expired in Redis
* before the cookie with the session ID in the browser, or a malicious
* client is trying to pull off a session fixation attack.
*
* @param string $session_id
*
Expand Down

0 comments on commit 50ec3fa

Please sign in to comment.