From c0ee24f3138fe6fc0978c87d746cd7fcdf88a529 Mon Sep 17 00:00:00 2001 From: psychon Date: Mon, 4 May 2009 19:21:26 +0000 Subject: [PATCH] Handle SIGCHLD for collecting zombie processes The old code failed to collect the following command to *shell correctly: exec > /dev/null 2> /dev/null < /dev/null ; sleep 10 The timeout in CExecSock::close2() was over before the child processes exited and a zombie was left behind. Plus we used some ugly busy looping while waiting for the child to exit. Using SIGCHLD for collecting zombies is soooooo much nicer. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1504 726aef4b-f618-498e-8847-2d620e286838 --- FileUtils.cpp | 7 +------ main.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/FileUtils.cpp b/FileUtils.cpp index c436b81a..d9150223 100644 --- a/FileUtils.cpp +++ b/FileUtils.cpp @@ -556,11 +556,6 @@ int CExecSock::popen2(int & iReadFD, int & iWriteFD, const CString & sCommand) { void CExecSock::close2(int iPid, int iReadFD, int iWriteFD) { close(iReadFD); close(iWriteFD); - u_int iNow = time(NULL); - while (waitpid(iPid, NULL, WNOHANG) == 0) { - if ((time(NULL) - iNow) > 5) - break; // giveup - usleep(100); - } + // If a zombie is left behind, SIGCHLD will handle it return; } diff --git a/main.cpp b/main.cpp index a77cd2f7..7ff172f9 100644 --- a/main.cpp +++ b/main.cpp @@ -8,6 +8,7 @@ #include "znc.h" #include +#include static const struct option g_LongOpts[] = { { "help", no_argument, 0, 'h' }, @@ -61,6 +62,11 @@ static void rehash(int sig) { CZNC::Get().SetNeedRehash(true); } +static void reapChilds(int sig) { + while (waitpid(-1, NULL, WNOHANG) > 0) { + } +} + static bool isRoot() { // User root? If one of these were root, we could switch the others to root, too if (geteuid() == 0 || getuid() == 0) @@ -242,6 +248,9 @@ int main(int argc, char** argv) { sa.sa_handler = rehash; sigaction(SIGHUP, &sa, (struct sigaction*) NULL); + sa.sa_handler = reapChilds; + sigaction(SIGCHLD, &sa, (struct sigaction*) NULL); + // Once this signal is caught, the signal handler is reset // to SIG_DFL. This avoids endless loop with signals. sa.sa_flags = SA_RESETHAND;