From 08cd3bf2924da099facdc1fa30706c93ad3b4871 Mon Sep 17 00:00:00 2001 From: Binbin Date: Mon, 13 Mar 2023 00:08:03 +0800 Subject: [PATCH] redis-cli reads specified number of replies for UNSUBSCRIBE/PUNSUBSCRIBE/SUNSUBSCRIBE (#11047) In unsubscribe related commands, we need to read the specified number of replies according to the number of parameters. These commands may return multiple RESP replies, and currently redis-cli only tries to read only one reply. Fixes #11046, this redis-cli bug seems to be there forever. Note that the [UN]SUBSCRIBE command response is a bit awkward see: https://github.com/redis/redis-doc/pull/2327 --- src/redis-cli.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/redis-cli.c b/src/redis-cli.c index 4e99e10994..964ae59ef9 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -1739,6 +1739,7 @@ static int cliSendCommand(int argc, char **argv, long repeat) { char *command = argv[0]; size_t *argvlen; int j, output_raw; + int is_unsubscribe_command = 0; /* Is it an unsubscribe related command? */ if (context == NULL) return REDIS_ERR; @@ -1777,6 +1778,9 @@ static int cliSendCommand(int argc, char **argv, long repeat) { if (!strcasecmp(command,"subscribe") || !strcasecmp(command,"psubscribe") || !strcasecmp(command,"ssubscribe")) config.pubsub_mode = 1; + if (!strcasecmp(command,"unsubscribe") || + !strcasecmp(command,"punsubscribe") || + !strcasecmp(command,"sunsubscribe")) is_unsubscribe_command = 1; if (!strcasecmp(command,"sync") || !strcasecmp(command,"psync")) config.slave_mode = 1; @@ -1807,6 +1811,22 @@ static int cliSendCommand(int argc, char **argv, long repeat) { works well with the interval option. */ while(repeat < 0 || repeat-- > 0) { redisAppendCommandArgv(context,argc,(const char**)argv,argvlen); + + if (is_unsubscribe_command) { + /* In unsubscribe related commands, we need to read the specified + * number of replies according to the number of parameters. */ + argc--; /* Skip the command */ + do { + if (cliReadReply(output_raw) != REDIS_OK) { + cliPrintContextError(); + exit(1); + } + fflush(stdout); + } while(--argc); + zfree(argvlen); + continue; + } + if (config.monitor_mode) { do { if (cliReadReply(output_raw) != REDIS_OK) {