]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
kevent() will return an error if the process has already exited
authorAlan T. DeKok <aland@freeradius.org>
Mon, 13 Apr 2020 21:50:08 +0000 (17:50 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 13 Apr 2020 21:50:08 +0000 (17:50 -0400)
so we just call waitpid() to reap its status

src/lib/util/event.c

index 027656ac1e72ca3303c242e005069f9f1027c0a4..2fb3e670d1bf5b2ad603e6f49b1e856f67c4697f 100644 (file)
@@ -1256,7 +1256,28 @@ int fr_event_pid_wait(TALLOC_CTX *ctx, fr_event_list_t *el, fr_event_pid_t const
        EV_SET(&evset, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, ev);
 
        if (unlikely(kevent(el->kq, &evset, 1, NULL, 0, NULL) < 0)) {
-               fr_strerror_printf("Failed adding waiter for PID %ld", (long) pid);
+               pid_t child;
+               int status;
+
+               talloc_free(ev);
+
+               /*
+                *      Print this error here, so that the caller gets
+                *      the error from kevent(), and not waitpid().
+                */
+               fr_strerror_printf("Failed adding waiter for PID %ld - %s", (long) pid, fr_syserror(errno));
+
+               /*
+                *      If the child exited before kevent() was
+                *      called, we need to get its status via
+                *      waitpid().
+                */
+               child = waitpid(pid, &status, WNOHANG);
+               if (child == pid) {
+                       wait_fn(el, pid, status, uctx);
+                       return 0;
+               }
+
                return -1;
        }
        talloc_set_destructor(ev, _event_pid_free);