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
6465ps_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
162161static 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
250250static 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