diff --git a/src/rdb.c b/src/rdb.c index 2c354bd5..5566acb0 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -1649,27 +1649,43 @@ int rdbSaveToSlavesSockets(void) { exitFromChild((retval == C_OK) ? 0 : 1); } else { /* Parent */ - zfree(clientids); /* Not used by parent. Free ASAP. */ server.stat_fork_time = ustime()-start; server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */ latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000); if (childpid == -1) { serverLog(LL_WARNING,"Can't save in background: fork: %s", strerror(errno)); - zfree(fds); + + /* Undo the state change. The caller will perform cleanup on + * all the slaves in BGSAVE_START state, but an early call to + * replicationSetupSlaveForFullResync() turned it into BGSAVE_END */ + listRewind(server.slaves,&li); + while((ln = listNext(&li))) { + client *slave = ln->value; + int j; + + for (j = 0; j < numfds; j++) { + if (slave->id == clientids[j]) { + slave->replstate = SLAVE_STATE_WAIT_BGSAVE_START; + break; + } + } + } close(pipefds[0]); close(pipefds[1]); - return C_ERR; + } else { + serverLog(LL_NOTICE,"Background RDB transfer started by pid %d", + childpid); + server.rdb_save_time_start = time(NULL); + server.rdb_child_pid = childpid; + server.rdb_child_type = RDB_CHILD_TYPE_SOCKET; + updateDictResizePolicy(); } - serverLog(LL_NOTICE,"Background RDB transfer started by pid %d",childpid); - server.rdb_save_time_start = time(NULL); - server.rdb_child_pid = childpid; - server.rdb_child_type = RDB_CHILD_TYPE_SOCKET; - updateDictResizePolicy(); + zfree(clientids); zfree(fds); - return C_OK; + return (childpid == -1) ? C_ERR : C_OK; } - return C_OK; /* unreached */ + return C_OK; /* Unreached. */ } void saveCommand(client *c) {