qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 03/11] slirp: Avoid zombie processes after fork_exec


From: Jan Kiszka
Subject: [Qemu-devel] [PATCH 03/11] slirp: Avoid zombie processes after fork_exec
Date: Fri, 08 May 2009 12:34:17 +0200
User-agent: StGIT/0.14.2

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 <address@hidden>
---

 net.c |   60 ++++++++++++++++++++++++++++++++++--------------------------
 vl.c  |   13 +++++++++++--
 2 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/net.c b/net.c
index 671138f..6a5c698 100644
--- a/net.c
+++ b/net.c
@@ -1049,38 +1049,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 867111c..81569f0 100644
--- a/vl.c
+++ b/vl.c
@@ -4780,7 +4780,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;
 
@@ -4789,6 +4794,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
@@ -5784,7 +5793,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 */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]