mirror of https://github.com/xqemu/xqemu.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 <jan.kiszka@siemens.com> Signed-off-by: Mark McLoughlin <markmc@redhat.com>
This commit is contained in:
parent
c27ff60871
commit
7c3370d4fe
58
net.c
58
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)
|
static int launch_script(const char *setup_script, const char *ifname, int fd)
|
||||||
{
|
{
|
||||||
|
sigset_t oldmask, mask;
|
||||||
int pid, status;
|
int pid, status;
|
||||||
char *args[3];
|
char *args[3];
|
||||||
char **parg;
|
char **parg;
|
||||||
|
|
||||||
/* try to launch network script */
|
sigemptyset(&mask);
|
||||||
pid = fork();
|
sigaddset(&mask, SIGCHLD);
|
||||||
if (pid >= 0) {
|
sigprocmask(SIG_BLOCK, &mask, &oldmask);
|
||||||
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;
|
/* try to launch network script */
|
||||||
*parg++ = (char *)setup_script;
|
pid = fork();
|
||||||
*parg++ = (char *)ifname;
|
if (pid == 0) {
|
||||||
*parg++ = NULL;
|
int open_max = sysconf(_SC_OPEN_MAX), i;
|
||||||
execv(setup_script, args);
|
|
||||||
_exit(1);
|
for (i = 0; i < open_max; i++) {
|
||||||
}
|
if (i != STDIN_FILENO &&
|
||||||
while (waitpid(pid, &status, 0) != pid);
|
i != STDOUT_FILENO &&
|
||||||
if (!WIFEXITED(status) ||
|
i != STDERR_FILENO &&
|
||||||
WEXITSTATUS(status) != 0) {
|
i != fd) {
|
||||||
fprintf(stderr, "%s: could not launch network script\n",
|
close(i);
|
||||||
setup_script);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,
|
static int net_tap_init(VLANState *vlan, const char *model,
|
||||||
|
|
13
vl.c
13
vl.c
|
@ -4783,7 +4783,12 @@ static void termsig_handler(int signal)
|
||||||
qemu_system_shutdown_request();
|
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;
|
struct sigaction act;
|
||||||
|
|
||||||
|
@ -4792,6 +4797,10 @@ static void termsig_setup(void)
|
||||||
sigaction(SIGINT, &act, NULL);
|
sigaction(SIGINT, &act, NULL);
|
||||||
sigaction(SIGHUP, &act, NULL);
|
sigaction(SIGHUP, &act, NULL);
|
||||||
sigaction(SIGTERM, &act, NULL);
|
sigaction(SIGTERM, &act, NULL);
|
||||||
|
|
||||||
|
act.sa_handler = sigchld_handler;
|
||||||
|
act.sa_flags = SA_NOCLDSTOP;
|
||||||
|
sigaction(SIGCHLD, &act, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5918,7 +5927,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/* must be after terminal init, SDL library changes signal handlers */
|
/* must be after terminal init, SDL library changes signal handlers */
|
||||||
termsig_setup();
|
sighandler_setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Maintain compatibility with multiple stdio monitors */
|
/* Maintain compatibility with multiple stdio monitors */
|
||||||
|
|
Loading…
Reference in New Issue