about summary refs log tree commit diff
path: root/src/process
diff options
context:
space:
mode:
authorAlexey Izbyshev <izbyshev@ispras.ru>2024-02-29 14:13:18 +0300
committerRich Felker <dalias@aerifal.cx>2024-02-29 10:07:03 -0500
commitd3a61059c04bd82329707324fac0d48e191edbf4 (patch)
tree4289e49a5272bbd4367f5d2d42a5383dcdb609de /src/process
parent80e3b09823a1d718664bc13704f3f7c19038a19e (diff)
downloadmusl-d3a61059c04bd82329707324fac0d48e191edbf4.tar.gz
musl-d3a61059c04bd82329707324fac0d48e191edbf4.tar.xz
musl-d3a61059c04bd82329707324fac0d48e191edbf4.zip
posix_spawn: fix child spinning on write to a broken pipe
A child process created by posix_spawn reports errors to its parent via
a pipe, retrying infinitely on any write error to prevent falsely
reporting success. If the (original) parent dies before write is
attempted, there is nobody to report to, but the child will remain
stuck in the write loop forever if SIGPIPE is blocked or ignored.
Fix this by not retrying write if it fails with EPIPE.
Diffstat (limited to 'src/process')
-rw-r--r--src/process/posix_spawn.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c
index 728551b3..8294598b 100644
--- a/src/process/posix_spawn.c
+++ b/src/process/posix_spawn.c
@@ -4,6 +4,7 @@
 #include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
+#include <errno.h>
 #include <sys/wait.h>
 #include "syscall.h"
 #include "lock.h"
@@ -156,7 +157,11 @@ static int child(void *args_vp)
 fail:
 	/* Since sizeof errno < PIPE_BUF, the write is atomic. */
 	ret = -ret;
-	if (ret) while (__syscall(SYS_write, p, &ret, sizeof ret) < 0);
+	if (ret) {
+		int r;
+		do r = __syscall(SYS_write, p, &ret, sizeof ret);
+		while (r<0 && r!=-EPIPE);
+	}
 	_exit(127);
 }