Blocking clients should not crash if an active replica loads a remote RDB with a key in the blocklist

Former-commit-id: 1c525e20b10e0a47af687a0d46faf75229a1cbf5
This commit is contained in:
John Sully 2020-11-19 23:28:01 +00:00
parent da2a3dbf99
commit e8753d1b4b
3 changed files with 26 additions and 1 deletions

View File

@ -672,6 +672,13 @@ void signalKeyAsReady(redisDb *db, robj *key) {
/* Key was already signaled? No need to queue it again. */ /* Key was already signaled? No need to queue it again. */
if (dictFind(db->ready_keys,key) != NULL) return; if (dictFind(db->ready_keys,key) != NULL) return;
if (key->getrefcount() == OBJ_STATIC_REFCOUNT) {
// Sometimes a key may be stack allocated, we'll need to dupe it
robj *newKey = createStringObject(szFromObj(key), sdslen(szFromObj(key)));
newKey->setrefcount(0); // Start with 0 but don't free
key = newKey;
}
/* Ok, we need to queue this key into g_pserver->ready_keys. */ /* Ok, we need to queue this key into g_pserver->ready_keys. */
rl = (readyList*)zmalloc(sizeof(*rl), MALLOC_SHARED); rl = (readyList*)zmalloc(sizeof(*rl), MALLOC_SHARED);
rl->key = key; rl->key = key;

View File

@ -3049,7 +3049,8 @@ struct redisMaster *replicationAddMaster(char *ip, int port) {
else else
freeClientAsync(mi->master); freeClientAsync(mi->master);
} }
disconnectAllBlockedClients(); /* Clients blocked in master, now replica. */ if (!g_pserver->fActiveReplica)
disconnectAllBlockedClients(); /* Clients blocked in master, now replica. */
/* Update oom_score_adj */ /* Update oom_score_adj */
setOOMScoreAdj(-1); setOOMScoreAdj(-1);

View File

@ -247,6 +247,23 @@ start_server {tags {"active-repl"} overrides {active-replica yes}} {
assert_equal {bar} [$master get testkey] {master is correct} assert_equal {bar} [$master get testkey] {master is correct}
} }
test {Active replica merge works with client blocked} {
$slave flushall
$slave replicaof no one
$master replicaof no one
after 100
set rd [redis_deferring_client]
$rd blpop testlist 0
$slave lpush testlist foo
#OK Now reconnect
$slave replicaof $master_host $master_port
$master replicaof $slave_host $slave_port
after 1000
$rd read
} {testlist foo}
test {Active replica different databases} { test {Active replica different databases} {
$master select 3 $master select 3
$master set testkey abcd $master set testkey abcd