[Top][All Lists]
[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 */