From 742e580f407cc6d922e2da54a50eb23dd017d5c4 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 21 Jan 2013 18:50:16 +0100 Subject: [PATCH] UNSUBSCRIBE and PUNSUBSCRIBE: always provide a reply. UNSUBSCRIBE and PUNSUBSCRIBE commands are designed to mass-unsubscribe the client respectively all the channels and patters if called without arguments. However when these functions are called without arguments, but there are no channels or patters we are subscribed to, the old behavior was to don't reply at all. This behavior is broken, as every command should always reply. Also it is possible that we are no longer subscribed to a channels but we are subscribed to patters or the other way around, and the client should be notified with the correct number of subscriptions. Also it is not pretty that sometimes we did not receive a reply at all in a redis-cli session from these commands, blocking redis-cli trying to read the reply. This fixes issue #714. --- src/pubsub.c | 16 ++++++++++++++++ tests/unit/pubsub.tcl | 12 +++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/pubsub.c b/src/pubsub.c index 97369294..3e58e385 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -179,6 +179,14 @@ int pubsubUnsubscribeAllChannels(redisClient *c, int notify) { count += pubsubUnsubscribeChannel(c,channel,notify); } + /* We were subscribed to nothing? Still reply to the client. */ + if (notify && count == 0) { + addReply(c,shared.mbulkhdr[3]); + addReply(c,shared.unsubscribebulk); + addReply(c,shared.nullbulk); + addReplyLongLong(c,dictSize(c->pubsub_channels)+ + listLength(c->pubsub_patterns)); + } dictReleaseIterator(di); return count; } @@ -196,6 +204,14 @@ int pubsubUnsubscribeAllPatterns(redisClient *c, int notify) { count += pubsubUnsubscribePattern(c,pattern,notify); } + if (notify && count == 0) { + /* We were subscribed to nothing? Still reply to the client. */ + addReply(c,shared.mbulkhdr[3]); + addReply(c,shared.punsubscribebulk); + addReply(c,shared.nullbulk); + addReplyLongLong(c,dictSize(c->pubsub_channels)+ + listLength(c->pubsub_patterns)); + } return count; } diff --git a/tests/unit/pubsub.tcl b/tests/unit/pubsub.tcl index c8b547b4..76915160 100644 --- a/tests/unit/pubsub.tcl +++ b/tests/unit/pubsub.tcl @@ -192,4 +192,14 @@ start_server {tags {"pubsub"}} { # clean up clients $rd1 close } -} \ No newline at end of file + + test "PUNSUBSCRIBE and UNSUBSCRIBE should always reply." { + # Make sure we are not subscribed to any channel at all. + r punsubscribe + r unsubscribe + # Now check if the commands still reply correctly. + set reply1 [r punsubscribe] + set reply2 [r unsubscribe] + concat $reply1 $reply2 + } {punsubscribe {} 0 unsubscribe {} 0} +}