Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 61889cd

Browse files
PHPREDIS-1412: Breaking the lock acquire loop in case of network problems
1 parent d71b6d5 commit 61889cd

1 file changed

Lines changed: 23 additions & 17 deletions

File tree

redis_session.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060

6161
/* Check if a response is the Redis +OK status response */
6262
#define IS_REDIS_OK(r, len) (r != NULL && len == 3 && !memcmp(r, "+OK", 3))
63+
#define NEGATIVE_LOCK_RESPONSE 1
6364

6465
ps_module ps_mod_redis = {
6566
#if (PHP_MAJOR_VERSION < 7)
@@ -143,20 +144,18 @@ redis_pool_free(redis_pool *pool TSRMLS_DC) {
143144
efree(pool);
144145
}
145146

146-
/* Send a command to Redis. Returns reply on success and NULL on failure */
147-
static char *redis_simple_cmd(RedisSock *redis_sock, char *cmd, int cmdlen,
148-
int *replylen TSRMLS_DC)
147+
/* Send a command to Redis. Returns byte count written to socket (-1 on failure) */
148+
static int redis_simple_cmd(RedisSock *redis_sock, char *cmd, int cmdlen,
149+
char **reply, int *replylen TSRMLS_DC)
149150
{
150-
char *reply;
151+
*reply = NULL;
152+
int len_written = redis_sock_write(redis_sock, cmd, cmdlen TSRMLS_CC);
151153

152-
if (redis_sock_write(redis_sock, cmd, cmdlen TSRMLS_CC) >= 0) {
153-
if ((reply = redis_sock_read(redis_sock, replylen TSRMLS_CC)) != NULL) {
154-
return reply;
155-
}
154+
if (len_written >= 0) {
155+
*reply = redis_sock_read(redis_sock, replylen TSRMLS_CC);
156156
}
157157

158-
/* Failed to send or receive command */
159-
return NULL;
158+
return len_written;
160159
}
161160

162161
static void
@@ -232,9 +231,9 @@ static int set_session_lock_key(RedisSock *redis_sock, char *cmd, int cmd_len
232231
TSRMLS_DC)
233232
{
234233
char *reply;
235-
int reply_len;
234+
int sent_len, reply_len;
236235

237-
reply = redis_simple_cmd(redis_sock, cmd, cmd_len, &reply_len TSRMLS_CC);
236+
sent_len = redis_simple_cmd(redis_sock, cmd, cmd_len, &reply, &reply_len TSRMLS_CC);
238237
if (reply) {
239238
if (IS_REDIS_OK(reply, reply_len)) {
240239
efree(reply);
@@ -244,14 +243,15 @@ static int set_session_lock_key(RedisSock *redis_sock, char *cmd, int cmd_len
244243
efree(reply);
245244
}
246245

247-
return FAILURE;
246+
/* Return FAILURE in case of network problems */
247+
return sent_len >= 0 ? NEGATIVE_LOCK_RESPONSE : FAILURE;
248248
}
249249

250250
static int lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_status
251251
TSRMLS_DC)
252252
{
253253
char *cmd, hostname[HOST_NAME_MAX] = {0}, suffix[] = "_LOCK", pid[32];
254-
int cmd_len, lock_wait_time, retries, i, expiry;
254+
int cmd_len, lock_wait_time, retries, i, set_lock_key_result, expiry;
255255

256256
/* Short circuit if we are already locked or not using session locks */
257257
if (lock_status->is_locked || !INI_INT("redis.session.locking_enabled"))
@@ -301,9 +301,15 @@ static int lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_s
301301

302302
/* Attempt to get our lock */
303303
for (i = 0; retries == -1 || i <= retries; i++) {
304-
if (set_session_lock_key(redis_sock, cmd, cmd_len TSRMLS_CC) == SUCCESS) {
304+
set_lock_key_result = set_session_lock_key(redis_sock, cmd, cmd_len TSRMLS_CC);
305+
306+
if (set_lock_key_result == SUCCESS) {
305307
lock_status->is_locked = 1;
306308
break;
309+
} else if (set_lock_key_result == FAILURE) {
310+
/* In case of network problems, break the loop and report to userland */
311+
lock_status->is_locked = 0;
312+
break;
307313
}
308314

309315
/* Sleep unless we're done making attempts */
@@ -339,7 +345,7 @@ static void refresh_lock_status(RedisSock *redis_sock, redis_session_lock_status
339345
cmdlen = REDIS_SPPRINTF(&cmd, "GET", "S", lock_status->lock_key);
340346

341347
/* Attempt to refresh the lock */
342-
reply = redis_simple_cmd(redis_sock, cmd, cmdlen, &replylen TSRMLS_CC);
348+
redis_simple_cmd(redis_sock, cmd, cmdlen, &reply, &replylen TSRMLS_CC);
343349
if (reply != NULL) {
344350
lock_status->is_locked = IS_LOCK_SECRET(reply, replylen, lock_status->lock_secret);
345351
efree(reply);
@@ -389,7 +395,7 @@ static void lock_release(RedisSock *redis_sock, redis_session_lock_status *lock_
389395
lock_status->lock_key, lock_status->lock_secret);
390396

391397
/* Send it off */
392-
reply = redis_simple_cmd(redis_sock, cmd, cmdlen, &replylen TSRMLS_CC);
398+
redis_simple_cmd(redis_sock, cmd, cmdlen, &reply, &replylen TSRMLS_CC);
393399

394400
/* Release lock and cleanup reply if we got one */
395401
if (reply != NULL) {

0 commit comments

Comments
 (0)