/* ISC license. */ #include #include #if defined(SKALIBS_HASPOSIXSPAWN) && defined(SKALIBS_HASPOSIXSPAWNEARLYRETURN) #include #include #include #include /* when posix_spawn returns too early, you need this */ pid_t cspawn_workaround (pid_t pid, int const *p) { siginfo_t si ; int e ; ssize_t r ; char c ; fd_close(p[1]) ; r = fd_read(p[0], &c, 1) ; fd_close(p[0]) ; if (r == -1) return 0 ; if (r) return (errno = EILSEQ, 0) ; /* child wrote, wtf */ do e = waitid(P_PID, pid, &si, WEXITED | WNOHANG | WNOWAIT) ; while (e == -1 && errno == EINTR) ; if (e == -1) return pid ; /* we're in trouble, but don't leak a child */ if (!si.si_pid) return pid ; /* child is running */ if (si.si_code != CLD_EXITED || si.si_status != 127) return pid ; /* child died after execve(), let caller handle it */ /* child exited 127, so either execve() failed, which is what we want to catch, or it raced like a mofo, execve()d and then exited 127 on its own, in which case, tough luck, it never existed. */ wait_pid(pid, 0) ; return (errno = 0, 0) ; } #else pid_t cspawn_workaround (pid_t pid, int const *p) { if (p) { fd_close(p[1]) ; fd_close(p[0]) ; } return pid ; } #endif