diff --git a/src/networking.c b/src/networking.c index 55daff85de495f0fadf003ea51d4403858c0e027..4c3db9379fe234431e33821aaec83ff5701d452f 100644 --- a/src/networking.c +++ b/src/networking.c @@ -456,6 +456,13 @@ void freeClient(redisClient *c) { ln = listSearchKey(server.clients,c); redisAssert(ln != NULL); listDelNode(server.clients,ln); + /* When client was just unblocked because of a blocking operation, + * remove it from the list with unblocked clients. */ + if (c->flags & REDIS_UNBLOCKED) { + ln = listSearchKey(server.unblocked_clients,c); + redisAssert(ln != NULL); + listDelNode(server.unblocked_clients,ln); + } /* Remove from the list of clients waiting for swapped keys, or ready * to be restarted, but not yet woken up again. */ if (c->flags & REDIS_IO_WAIT) { diff --git a/src/redis.c b/src/redis.c index 5aabe3bcb10c3d8605cbc792389cecfd412a17d7..af956e9162f7e93a7a37fde4efdd9fe0bb8131ec 100644 --- a/src/redis.c +++ b/src/redis.c @@ -688,6 +688,7 @@ void beforeSleep(struct aeEventLoop *eventLoop) { redisAssert(ln != NULL); c = ln->value; listDelNode(server.unblocked_clients,ln); + c->flags &= ~REDIS_UNBLOCKED; /* Process remaining data in the input buffer. */ if (c->querybuf && sdslen(c->querybuf) > 0) diff --git a/src/redis.h b/src/redis.h index 3bfe4cd5b4613158b38112059f9a759751c04be5..aa42e2c4ac2c4d9db1529c60dcbe849ae39f69e8 100644 --- a/src/redis.h +++ b/src/redis.h @@ -136,6 +136,8 @@ #define REDIS_IO_WAIT 32 /* The client is waiting for Virtual Memory I/O */ #define REDIS_DIRTY_CAS 64 /* Watched keys modified. EXEC will fail. */ #define REDIS_CLOSE_AFTER_REPLY 128 /* Close after writing entire reply. */ +#define REDIS_UNBLOCKED 256 /* This client was unblocked and is stored in + server.unblocked_clients */ /* Client request types */ #define REDIS_REQ_INLINE 1 diff --git a/src/t_list.c b/src/t_list.c index d5db6feb324c21e7811203e0ed320662d6e0dd4c..1c658353509f37bed0a12728ac7d1b54bca1835f 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -773,7 +773,8 @@ void unblockClientWaitingData(redisClient *c) { zfree(c->bpop.keys); c->bpop.keys = NULL; c->bpop.target = NULL; - c->flags &= (~REDIS_BLOCKED); + c->flags &= ~REDIS_BLOCKED; + c->flags |= REDIS_UNBLOCKED; server.bpop_blocked_clients--; listAddNodeTail(server.unblocked_clients,c); }