add a service to reap zombies, use it in SLIRP
SLIRP -smb support wants to fork a process and forget about reaping it. To please it, add a generic service to register a process id and let QEMU reap it. In the future it could be enhanced to pass a status, but this would be unused. With this in place, the SIGCHLD signal handler would not stomp on pclose anymore. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
0298141998
commit
4d54ec7898
64
iohandler.c
64
iohandler.c
@ -27,6 +27,10 @@
|
||||
#include "qemu-char.h"
|
||||
#include "qemu-queue.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
typedef struct IOHandlerRecord {
|
||||
int fd;
|
||||
IOCanReadHandler *fd_read_poll;
|
||||
@ -127,3 +131,63 @@ void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int re
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* reaping of zombies. right now we're not passing the status to
|
||||
anyone, but it would be possible to add a callback. */
|
||||
#ifndef _WIN32
|
||||
typedef struct ChildProcessRecord {
|
||||
int pid;
|
||||
QLIST_ENTRY(ChildProcessRecord) next;
|
||||
} ChildProcessRecord;
|
||||
|
||||
static QLIST_HEAD(, ChildProcessRecord) child_watches =
|
||||
QLIST_HEAD_INITIALIZER(child_watches);
|
||||
|
||||
static QEMUBH *sigchld_bh;
|
||||
|
||||
static void sigchld_handler(int signal)
|
||||
{
|
||||
qemu_bh_schedule(sigchld_bh);
|
||||
}
|
||||
|
||||
static void sigchld_bh_handler(void *opaque)
|
||||
{
|
||||
ChildProcessRecord *rec, *next;
|
||||
|
||||
QLIST_FOREACH_SAFE(rec, &child_watches, next, next) {
|
||||
if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) {
|
||||
QLIST_REMOVE(rec, next);
|
||||
qemu_free(rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_init_child_watch(void)
|
||||
{
|
||||
struct sigaction act;
|
||||
sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL);
|
||||
|
||||
act.sa_handler = sigchld_handler;
|
||||
act.sa_flags = SA_NOCLDSTOP;
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
}
|
||||
|
||||
int qemu_add_child_watch(pid_t pid)
|
||||
{
|
||||
ChildProcessRecord *rec;
|
||||
|
||||
if (!sigchld_bh) {
|
||||
qemu_init_child_watch();
|
||||
}
|
||||
|
||||
QLIST_FOREACH(rec, &child_watches, next) {
|
||||
if (rec->pid == pid) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
rec = qemu_mallocz(sizeof(ChildProcessRecord));
|
||||
rec->pid = pid;
|
||||
QLIST_INSERT_HEAD(&child_watches, rec, next);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -67,11 +67,6 @@ static void termsig_handler(int signal, siginfo_t *info, void *c)
|
||||
qemu_system_killed(info->si_signo, info->si_pid);
|
||||
}
|
||||
|
||||
static void sigchld_handler(int signal)
|
||||
{
|
||||
waitpid(-1, NULL, WNOHANG);
|
||||
}
|
||||
|
||||
void os_setup_signal_handling(void)
|
||||
{
|
||||
struct sigaction act;
|
||||
@ -82,10 +77,6 @@ void os_setup_signal_handling(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);
|
||||
}
|
||||
|
||||
/* Find a likely location for support files using the location of the binary.
|
||||
|
@ -214,6 +214,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
|
||||
void qemu_set_cloexec(int fd);
|
||||
|
||||
#ifndef _WIN32
|
||||
int qemu_add_child_watch(pid_t pid);
|
||||
int qemu_eventfd(int pipefd[2]);
|
||||
int qemu_pipe(int pipefd[2]);
|
||||
#endif
|
||||
|
@ -119,6 +119,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
char *bptr;
|
||||
const char *curarg;
|
||||
int c, i, ret;
|
||||
pid_t pid;
|
||||
|
||||
DEBUG_CALL("fork_exec");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
@ -142,7 +143,8 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
}
|
||||
}
|
||||
|
||||
switch(fork()) {
|
||||
pid = fork();
|
||||
switch(pid) {
|
||||
case -1:
|
||||
lprint("Error: fork failed: %s\n", strerror(errno));
|
||||
close(s);
|
||||
@ -206,6 +208,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
exit(1);
|
||||
|
||||
default:
|
||||
qemu_add_child_watch(pid);
|
||||
if (do_pty == 2) {
|
||||
close(s);
|
||||
so->s = master;
|
||||
|
Loading…
Reference in New Issue
Block a user