Skip to content

Commit

Permalink
Kill diskless fork child asap when the last replica drop (#1227)
Browse files Browse the repository at this point in the history
We originally checked the replica connection to whether to kill the
diskless child only when rdbPipeReadHandler is triggered. Actually
we can check it when the replica is disconnected, so that we don't
have to wait for rdbPipeReadHandler to be triggered and can kill
the forkless child as soon as possible.

In this way, when the child or rdbPipeReadHandler is stuck for some
reason, we can kill the child faster and release the fork resources.

Signed-off-by: Binbin <[email protected]>
  • Loading branch information
enjoy-binbin authored Nov 15, 2024
1 parent d3f3b9c commit 4e2493e
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 9 deletions.
8 changes: 7 additions & 1 deletion src/networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -1555,12 +1555,17 @@ void unlinkClient(client *c) {
* in which case it needs to be cleaned from that list */
if (c->flag.replica && c->repl_state == REPLICA_STATE_WAIT_BGSAVE_END && server.rdb_pipe_conns) {
int i;
int still_alive = 0;
for (i = 0; i < server.rdb_pipe_numconns; i++) {
if (server.rdb_pipe_conns[i] == c->conn) {
rdbPipeWriteHandlerConnRemoved(c->conn);
server.rdb_pipe_conns[i] = NULL;
break;
}
if (server.rdb_pipe_conns[i]) still_alive++;
}
if (still_alive == 0) {
serverLog(LL_NOTICE, "Diskless rdb transfer, last replica dropped, killing fork child.");
killRDBChild();
}
}
/* Only use shutdown when the fork is active and we are the parent. */
Expand Down Expand Up @@ -1781,6 +1786,7 @@ void freeClient(client *c) {
if (server.saveparamslen == 0 && c->repl_state == REPLICA_STATE_WAIT_BGSAVE_END &&
server.child_type == CHILD_TYPE_RDB && server.rdb_child_type == RDB_CHILD_TYPE_DISK &&
anyOtherReplicaWaitRdb(c) == 0) {
serverLog(LL_NOTICE, "Background saving, persistence disabled, last replica dropped, killing fork child.");
killRDBChild();
}
if (c->repl_state == REPLICA_STATE_SEND_BULK) {
Expand Down
12 changes: 4 additions & 8 deletions src/replication.c
Original file line number Diff line number Diff line change
Expand Up @@ -1669,7 +1669,9 @@ void rdbPipeReadHandler(struct aeEventLoop *eventLoop, int fd, void *clientData,
if (!conn) continue;
stillUp++;
}
serverLog(LL_NOTICE, "Diskless rdb transfer, done reading from pipe, %d replicas still up.", stillUp);
if (stillUp) {
serverLog(LL_NOTICE, "Diskless rdb transfer, done reading from pipe, %d replicas still up.", stillUp);
}
/* Now that the replicas have finished reading, notify the child that it's safe to exit.
* When the server detects the child has exited, it can mark the replica as online, and
* start streaming the replication buffers. */
Expand All @@ -1678,7 +1680,6 @@ void rdbPipeReadHandler(struct aeEventLoop *eventLoop, int fd, void *clientData,
return;
}

int stillAlive = 0;
for (i = 0; i < server.rdb_pipe_numconns; i++) {
ssize_t nwritten;
connection *conn = server.rdb_pipe_conns[i];
Expand Down Expand Up @@ -1708,15 +1709,10 @@ void rdbPipeReadHandler(struct aeEventLoop *eventLoop, int fd, void *clientData,
server.rdb_pipe_numconns_writing++;
connSetWriteHandler(conn, rdbPipeWriteHandler);
}
stillAlive++;
}

if (stillAlive == 0) {
serverLog(LL_WARNING, "Diskless rdb transfer, last replica dropped, killing fork child.");
killRDBChild();
}
/* Remove the pipe read handler if at least one write handler was set. */
if (server.rdb_pipe_numconns_writing || stillAlive == 0) {
if (server.rdb_pipe_numconns_writing) {
aeDeleteFileEvent(server.el, server.rdb_pipe_read, AE_READABLE);
break;
}
Expand Down

0 comments on commit 4e2493e

Please sign in to comment.