Skip to content

Commit 50ec3fa

Browse files
committed
address issue #1: spinlock should usleep
1 parent 0ac53e0 commit 50ec3fa

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

RedisSessionHandler.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@
77
*/
88
class RedisSessionHandler extends \SessionHandler
99
{
10+
/**
11+
* Wait time (1ms) after first locking attempt. It doubles
12+
* for every unsuccessful retry until it either reaches
13+
* MAX_WAIT_TIME or succeeds.
14+
*/
15+
const MIN_WAIT_TIME = 1000;
16+
17+
/**
18+
* Maximum wait time (128ms) between locking attempts.
19+
*/
20+
const MAX_WAIT_TIME = 128000;
21+
1022
/**
1123
* @var \Redis
1224
*/
@@ -161,7 +173,15 @@ public function gc($maxlifetime)
161173
*/
162174
private function acquireLockOn($session_id)
163175
{
164-
while (false === $this->redis->set("{$session_id}_lock", '', ['nx', 'ex' => $this->lock_ttl]));
176+
$wait = self::MIN_WAIT_TIME;
177+
178+
while (false === $this->redis->set("{$session_id}_lock", '', ['nx', 'ex' => $this->lock_ttl])) {
179+
usleep($wait);
180+
181+
if (self::MAX_WAIT_TIME > $wait) {
182+
$wait *= 2;
183+
}
184+
}
165185

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

0 commit comments

Comments
 (0)