Selaa lähdekoodia

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>
Paolo Bonzini 14 vuotta sitten
vanhempi
commit
4d54ec7898
4 muutettua tiedostoa jossa 69 lisäystä ja 10 poistoa
  1. 64 0
      iohandler.c
  2. 0 9
      os-posix.c
  3. 1 0
      qemu-common.h
  4. 4 1
      slirp/misc.c

+ 64 - 0
iohandler.c

@@ -27,6 +27,10 @@
 #include "qemu-char.h"
 #include "qemu-char.h"
 #include "qemu-queue.h"
 #include "qemu-queue.h"
 
 
+#ifndef _WIN32
+#include <sys/wait.h>
+#endif
+
 typedef struct IOHandlerRecord {
 typedef struct IOHandlerRecord {
     int fd;
     int fd;
     IOCanReadHandler *fd_read_poll;
     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

+ 0 - 9
os-posix.c

@@ -67,11 +67,6 @@ static void termsig_handler(int signal, siginfo_t *info, void *c)
     qemu_system_killed(info->si_signo, info->si_pid);
     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)
 void os_setup_signal_handling(void)
 {
 {
     struct sigaction act;
     struct sigaction act;
@@ -82,10 +77,6 @@ void os_setup_signal_handling(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);
 }
 }
 
 
 /* Find a likely location for support files using the location of the binary.
 /* Find a likely location for support files using the location of the binary.

+ 1 - 0
qemu-common.h

@@ -214,6 +214,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
 void qemu_set_cloexec(int fd);
 void qemu_set_cloexec(int fd);
 
 
 #ifndef _WIN32
 #ifndef _WIN32
+int qemu_add_child_watch(pid_t pid);
 int qemu_eventfd(int pipefd[2]);
 int qemu_eventfd(int pipefd[2]);
 int qemu_pipe(int pipefd[2]);
 int qemu_pipe(int pipefd[2]);
 #endif
 #endif

+ 4 - 1
slirp/misc.c

@@ -119,6 +119,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 	char *bptr;
 	char *bptr;
 	const char *curarg;
 	const char *curarg;
 	int c, i, ret;
 	int c, i, ret;
+	pid_t pid;
 
 
 	DEBUG_CALL("fork_exec");
 	DEBUG_CALL("fork_exec");
 	DEBUG_ARG("so = %lx", (long)so);
 	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:
 	 case -1:
 		lprint("Error: fork failed: %s\n", strerror(errno));
 		lprint("Error: fork failed: %s\n", strerror(errno));
 		close(s);
 		close(s);
@@ -206,6 +208,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 		exit(1);
 		exit(1);
 
 
 	 default:
 	 default:
+		qemu_add_child_watch(pid);
 		if (do_pty == 2) {
 		if (do_pty == 2) {
 			close(s);
 			close(s);
 			so->s = master;
 			so->s = master;