From b915c9a6610b5cd0fb67e39ba9feff59fe23035d Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 13 Jan 2025 10:56:19 +0000 Subject: [PATCH] Attempt to keep running if a child process dies. If a child process dies unexpectedly, log the error and try and tidy up so the main process continues to run and doesn't block awaiting the dead child. --- src/dnsmasq.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/dnsmasq.c b/src/dnsmasq.c index fc35018..5b89455 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -1484,7 +1484,7 @@ static void async_event(int pipe, time_t now) { pid_t p; struct event_desc ev; - int i, check = 0; + int wstatus, i, check = 0; char *msg; /* NOTE: the memory used to return msg is leaked: use msgs in events only @@ -1547,7 +1547,7 @@ static void async_event(int pipe, time_t now) case EVENT_CHILD: /* See Stevens 5.10 */ - while ((p = waitpid(-1, NULL, WNOHANG)) != 0) + while ((p = waitpid(-1, &wstatus, WNOHANG)) != 0) if (p == -1) { if (errno != EINTR) @@ -1558,6 +1558,20 @@ static void async_event(int pipe, time_t now) if (daemon->tcp_pids[i] == p) { daemon->tcp_pids[i] = 0; + + if (!WIFEXITED(wstatus)) + { + /* If a helper process dies, (eg with SIGSEV) + log that and attempt to patch things up so that the + parent can continue to function. */ + my_syslog(LOG_WARNING, _("TCP helper process %u died unexpectedly"), (unsigned int)p); + if (daemon->tcp_pipes[i] != -1) + { + close(daemon->tcp_pipes[i]); + daemon->tcp_pipes[i] = -1; + } + } + /* tcp_pipes == -1 && tcp_pids == 0 required to free slot */ if (daemon->tcp_pipes[i] == -1) daemon->metrics[METRIC_TCP_CONNECTIONS]--; @@ -2092,7 +2106,7 @@ static void do_tcp_connection(struct listener *listener, time_t now, int slot) Reset that here. */ if ((flags = fcntl(confd, F_GETFL, 0)) != -1) while(retry_send(fcntl(confd, F_SETFL, flags & ~O_NONBLOCK))); - + buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns); if (buff)