process: Avoid stealing pclose()'s exit status.
authorBen Pfaff <blp@nicira.com>
Wed, 21 Jan 2009 00:06:59 +0000 (16:06 -0800)
committerBen Pfaff <blp@nicira.com>
Wed, 21 Jan 2009 00:44:14 +0000 (16:44 -0800)
When we use popen() and pclose(), pclose() wants to return the process's
exit status, but it can't if the SIGCHLD handler gets it first.  So,
instead of asking for any child process exit status in sigchld_handler(),
only ask for the exit status of registered PIDs.

lib/process.c

index d787b7bf94f3b15b97be195910c41120b949c905..087ca6b87da891f639bad04c63954e9c5d110e6c 100644 (file)
@@ -337,21 +337,22 @@ process_wait(struct process *p)
 static void
 sigchld_handler(int signr UNUSED)
 {
-    for (;;) {
-        struct process *p;
-        int status;
-        pid_t pid;
-
-        pid = waitpid(-1, &status, WNOHANG);
-        if (pid <= 0) {
-            break;
-        }
+    struct process *p;
 
-        LIST_FOR_EACH (p, struct process, node, &all_processes) {
-            if (p->pid == pid) {
+    LIST_FOR_EACH (p, struct process, node, &all_processes) {
+        if (!p->exited) {
+            int retval, status;
+            do {
+                retval = waitpid(p->pid, &status, WNOHANG);
+            } while (retval == -1 && errno == EINTR);
+            if (retval == p->pid) {
                 p->exited = true;
                 p->status = status;
-                break;
+            } else if (retval < 0) {
+                /* XXX We want to log something but we're in a signal
+                 * handler. */
+                p->exited = true;
+                p->status = -1;
             }
         }
     }