sim-card
/
qemu
Archived
10
0
Fork 0

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:
Paolo Bonzini 2011-03-09 18:21:10 +01:00 committed by Anthony Liguori
parent 0298141998
commit 4d54ec7898
4 changed files with 69 additions and 10 deletions

View File

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

View File

@ -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.

View File

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

View File

@ -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;