From: Jan Kiszka Date: Fri, 8 May 2009 10:34:17 +0000 (+0200) Subject: slirp: Avoid zombie processes after fork_exec X-Git-Tag: v2.7.1~12723^2~25 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=7c3370d4fe3fa6cda8655f109e4659afc8ca4269;p=mirror_qemu.git slirp: Avoid zombie processes after fork_exec Slirp uses fork_exec for spawning service processes, and QEMU uses this for running smbd. As SIGCHLD is not handled, these processes become zombies on termination. Fix this by installing a proper signal handler, but also make sure we disable the signal while waiting on forked network setup/shutdown scripts. Signed-off-by: Jan Kiszka Signed-off-by: Mark McLoughlin --- diff --git a/net.c b/net.c index 6563b424ce..97e1ac5ccd 100644 --- a/net.c +++ b/net.c @@ -1134,38 +1134,46 @@ static int tap_open(char *ifname, int ifname_size) static int launch_script(const char *setup_script, const char *ifname, int fd) { + sigset_t oldmask, mask; int pid, status; char *args[3]; char **parg; - /* try to launch network script */ - pid = fork(); - if (pid >= 0) { - if (pid == 0) { - int open_max = sysconf (_SC_OPEN_MAX), i; - for (i = 0; i < open_max; i++) - if (i != STDIN_FILENO && - i != STDOUT_FILENO && - i != STDERR_FILENO && - i != fd) - close(i); - - parg = args; - *parg++ = (char *)setup_script; - *parg++ = (char *)ifname; - *parg++ = NULL; - execv(setup_script, args); - _exit(1); - } - while (waitpid(pid, &status, 0) != pid); - if (!WIFEXITED(status) || - WEXITSTATUS(status) != 0) { - fprintf(stderr, "%s: could not launch network script\n", - setup_script); - return -1; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &mask, &oldmask); + + /* try to launch network script */ + pid = fork(); + if (pid == 0) { + int open_max = sysconf(_SC_OPEN_MAX), i; + + for (i = 0; i < open_max; i++) { + if (i != STDIN_FILENO && + i != STDOUT_FILENO && + i != STDERR_FILENO && + i != fd) { + close(i); } } - return 0; + parg = args; + *parg++ = (char *)setup_script; + *parg++ = (char *)ifname; + *parg++ = NULL; + execv(setup_script, args); + _exit(1); + } else if (pid > 0) { + while (waitpid(pid, &status, 0) != pid) { + /* loop */ + } + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return 0; + } + } + fprintf(stderr, "%s: could not launch network script\n", setup_script); + return -1; } static int net_tap_init(VLANState *vlan, const char *model, diff --git a/vl.c b/vl.c index fcf853222c..a5f966d4c7 100644 --- a/vl.c +++ b/vl.c @@ -4783,7 +4783,12 @@ static void termsig_handler(int signal) qemu_system_shutdown_request(); } -static void termsig_setup(void) +static void sigchld_handler(int signal) +{ + waitpid(-1, NULL, WNOHANG); +} + +static void sighandler_setup(void) { struct sigaction act; @@ -4792,6 +4797,10 @@ static void termsig_setup(void) sigaction(SIGINT, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGTERM, &act, NULL); + + act.sa_handler = sigchld_handler; + act.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &act, NULL); } #endif @@ -5918,7 +5927,7 @@ int main(int argc, char **argv, char **envp) #ifndef _WIN32 /* must be after terminal init, SDL library changes signal handlers */ - termsig_setup(); + sighandler_setup(); #endif /* Maintain compatibility with multiple stdio monitors */