diff --git a/src/networking.c b/src/networking.c index 10b9580e..a39be7c4 100644 --- a/src/networking.c +++ b/src/networking.c @@ -255,7 +255,8 @@ void freeClient(redisClient *c) { server.vm_blocked_clients--; } listRelease(c->io_keys); - /* Master/slave cleanup */ + /* Master/slave cleanup. + * Case 1: we lost the connection with a slave. */ if (c->flags & REDIS_SLAVE) { if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1) close(c->repldbfd); @@ -264,9 +265,20 @@ void freeClient(redisClient *c) { redisAssert(ln != NULL); listDelNode(l,ln); } + + /* Case 2: we lost the connection with the master. */ if (c->flags & REDIS_MASTER) { server.master = NULL; server.replstate = REDIS_REPL_CONNECT; + /* Since we lost the connection with the master, we should also + * close the connection with all our slaves if we have any, so + * when we'll resync with the master the other slaves will sync again + * with us as well. Note that also when the slave is not connected + * to the master it will keep refusing connections by other slaves. */ + while (listLength(server.slaves)) { + ln = listFirst(server.slaves); + freeClient((redisClient*)ln->value); + } } /* Release memory */ zfree(c->argv); diff --git a/src/replication.c b/src/replication.c index 5387db91..89375820 100644 --- a/src/replication.c +++ b/src/replication.c @@ -176,6 +176,13 @@ void syncCommand(redisClient *c) { /* ignore SYNC if aleady slave or in monitor mode */ if (c->flags & REDIS_SLAVE) return; + /* Refuse SYNC requests if we are a slave but the link with our master + * is not ok... */ + if (server.masterhost && server.replstate != REDIS_REPL_CONNECTED) { + addReplySds(c,sdsnew("-ERR Can't SYNC while not connected with my master\r\n")); + return; + } + /* SYNC can't be issued when the server has pending data to send to * the client about already issued commands. We need a fresh reply * buffer registering the differences between the BGSAVE and the current @@ -392,7 +399,12 @@ int syncWithMaster(void) { strerror(errno)); return REDIS_ERR; } - if (buf[0] != '$') { + if (buf[0] == '-') { + close(fd); + redisLog(REDIS_WARNING,"MASTER aborted replication with an error: %s", + buf+1); + return REDIS_ERR; + } else if (buf[0] != '$') { close(fd); redisLog(REDIS_WARNING,"Bad protocol from MASTER, the first byte is not '$', are you sure the host and port are right?"); return REDIS_ERR;