aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstddjb/child_spawn_workaround.c
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-06-28 21:27:29 +0000
committerLaurent Bercot <ska@appnovation.com>2023-06-28 21:27:29 +0000
commit28e09b5eb76919122f8baf57899154b3dd5fdaa0 (patch)
tree21559ec98d7f0f876fa0e2a5115744e396fd68d0 /src/libstddjb/child_spawn_workaround.c
parentd64a3751ca805c08bfda6a330d73a09e87e993c0 (diff)
downloadskalibs-28e09b5eb76919122f8baf57899154b3dd5fdaa0.tar.gz
Add workaround for bad QoI posix_spawn()
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/libstddjb/child_spawn_workaround.c')
-rw-r--r--src/libstddjb/child_spawn_workaround.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/libstddjb/child_spawn_workaround.c b/src/libstddjb/child_spawn_workaround.c
new file mode 100644
index 0000000..00f8553
--- /dev/null
+++ b/src/libstddjb/child_spawn_workaround.c
@@ -0,0 +1,48 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+
+#if defined(SKALIBS_HASPOSIXSPAWN) && defined(SKALIBS_HASPOSIXSPAWNEARLYRETURN)
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include <skalibs/allreadwrite.h>
+#include <skalibs/djbunix.h>
+#include "child_spawn-internal.h"
+
+pid_t child_spawn_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, 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
+
+ /* avoid empty TUs */
+
+extern int skalibs_child_spawn_workaround_dummy_ ;
+
+#endif