Commit 7c3370d4 authored by Jan Kiszka's avatar Jan Kiszka Committed by Mark McLoughlin
Browse files

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: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarMark McLoughlin <markmc@redhat.com>
parent c27ff608
Loading
Loading
Loading
Loading
+34 −26
Original line number Diff line number Diff line
@@ -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;

    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &mask, &oldmask);

    /* 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++)

        for (i = 0; i < open_max; i++) {
            if (i != STDIN_FILENO &&
                i != STDOUT_FILENO &&
                i != STDERR_FILENO &&
                        i != fd)
                i != fd) {
                close(i);

            }
        }
        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 */
        }
            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;
        sigprocmask(SIG_SETMASK, &oldmask, NULL);

        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
            return 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,
+11 −2
Original line number Diff line number Diff line
@@ -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 */