From 6204182aae71ca321418c069eac907936eeaa33a Mon Sep 17 00:00:00 2001 From: michael-grunder Date: Tue, 15 Dec 2020 17:46:11 -0800 Subject: Handle the case where an invalidation is sent second. RESP3 invalidation messages always seemed to be sent before the response to a given command, but it appears this is not always the case: In Redis 6.2.0RC1 Redis sends the invalidation after the HSET in the following sequence: ``` hget hash field $5 value hset hash field value :0 >2 $10 invalidate *1 $4 hash ``` To account for this possibility just wrap redisGetReplyFromReader in a loop as it is called twice in redisGetReply. --- hiredis.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/hiredis.c b/hiredis.c index 2c1fb82..f23ff45 100644 --- a/hiredis.c +++ b/hiredis.c @@ -994,17 +994,6 @@ oom: return REDIS_ERR; } -/* Internal helper function to try and get a reply from the reader, - * or set an error in the context otherwise. */ -int redisGetReplyFromReader(redisContext *c, void **reply) { - if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } - - return REDIS_OK; -} - /* Internal helper that returns 1 if the reply was a RESP3 PUSH * message and we handled it with a user-provided callback. */ static int redisHandledPushReply(redisContext *c, void *reply) { @@ -1016,6 +1005,19 @@ static int redisHandledPushReply(redisContext *c, void *reply) { return 0; } +/* Internal helper function to try and get a reply from the reader, + * or set an error in the context otherwise. */ +int redisGetReplyFromReader(redisContext *c, void **reply) { + do { + if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { + __redisSetError(c,c->reader->err,c->reader->errstr); + return REDIS_ERR; + } + } while (redisHandledPushReply(c, *reply)); + + return REDIS_OK; +} + int redisGetReply(redisContext *c, void **reply) { int wdone = 0; void *aux = NULL; @@ -1037,12 +1039,8 @@ int redisGetReply(redisContext *c, void **reply) { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; - /* We loop here in case the user has specified a RESP3 - * PUSH handler (e.g. for client tracking). */ - do { - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) - return REDIS_ERR; - } while (redisHandledPushReply(c, aux)); + if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) + return REDIS_ERR; } while (aux == NULL); } -- cgit v1.2.3