aboutsummaryrefslogtreecommitdiff
path: root/iohandler.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2011-03-09 18:21:10 +0100
committerAnthony Liguori <aliguori@us.ibm.com>2011-03-29 08:14:11 -0500
commit4d54ec7898bd951007cb6122d5315584bd41d0c4 (patch)
treee96c20c18a4ef32efe87295a70d17316757832cb /iohandler.c
parent0298141998ea3e19fd86b5a7122aab2fd1ebad51 (diff)
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>
Diffstat (limited to 'iohandler.c')
-rw-r--r--iohandler.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/iohandler.c b/iohandler.c
index 2e30fe3bcb..2b824218e5 100644
--- a/iohandler.c
+++ b/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