From 4cce87557feb6933c284d234c448bd8bde4facae Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Sat, 9 Sep 2023 03:55:38 +0000 Subject: cspawn revamp, part 1. Prepare for 2.14.0.0. Signed-off-by: Laurent Bercot --- src/libstddjb/cspawn_workaround.c | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/libstddjb/cspawn_workaround.c (limited to 'src/libstddjb/cspawn_workaround.c') diff --git a/src/libstddjb/cspawn_workaround.c b/src/libstddjb/cspawn_workaround.c new file mode 100644 index 0000000..da9bd89 --- /dev/null +++ b/src/libstddjb/cspawn_workaround.c @@ -0,0 +1,55 @@ +/* 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 -- cgit v1.2.3