Skip to content

Commit 4170c8d

Browse files
committed
lib: fix system() inheriting blocked SIGCHLD mask in child process
When a timeout is specified, system() blocks SIGCHLD in the parent to use sigtimedwait(). This blocked signal mask is inherited by the forked child, preventing the spawned shell from receiving SIGCHLD for its own subprocesses, causing zombie processes and hung wait() calls. Restore the original signal mask in the child before exec(). Fixes: #382 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
1 parent 591d1f6 commit 4170c8d

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎lib.c‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4042,7 +4042,9 @@ uc_system(uc_vm_t *vm, size_t nargs)
40424042
goto fail;
40434043

40444044
case 0:
4045-
execvp(arglist[0], (char * const *)arglist);
4045+
if (tms <= 0 || sigprocmask(SIG_SETMASK, &sigomask, NULL) == 0)
4046+
execvp(arglist[0], (char * const *)arglist);
4047+
40464048
exit(-1);
40474049

40484050
break;

‎tests/custom/03_stdlib/38_system‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,29 @@ In line 2, byte 23:
146146

147147

148148
-- End --
149+
150+
151+
When a timeout is specified, the child process must not inherit the blocked
152+
SIGCHLD signal mask. If it did, the shell's `wait` builtin would hang, as the
153+
shell could not receive SIGCHLD notifications for its own subprocesses.
154+
155+
-- Testcase --
156+
{%
157+
// Run a shell that backgrounds a child and waits for it; if SIGCHLD is
158+
// blocked in the child, the wait hangs and the timeout kills the process.
159+
let rc = system([ '/bin/sh', TESTFILES_PATH + '/testscripts/wait.sh' ], 5000);
160+
161+
print(rc == 0 ? "wait completed\n" : "wait failed\n");
162+
%}
163+
-- End --
164+
165+
-- File testscripts/wait.sh --
166+
#!/bin/sh
167+
168+
sleep 0 &
169+
wait
170+
-- End --
171+
172+
-- Expect stdout --
173+
wait completed
174+
-- End --

0 commit comments

Comments
 (0)