See: $ trap uname chld $ uname -sr Linux 5.4.0-66-generic Linux $ uname -sr Linux 5.4.0-66-generic Linux Linux $ uname -sr Linux 5.4.0-66-generic Linux Linux Linux $ $ trap - chld $ trap date chld $ uname -sr Linux 5.4.0-66-generic Sat 03 Apr 2021 10:15:21 AM +03 Sat 03 Apr 2021 10:15:21 AM +03 Sat 03 Apr 2021 10:15:21 AM +03 Sat 03 Apr 2021 10:15:21 AM +03
Now, that a SIGCHLD trap is queued for each subshell including those created while the trap handler is being executed kind of makes sense, but I don't think it's useful at all because the number of pending traps keeps piling up, and there is no way to reset that number. If there is no real use case for recursive SIGCHLD traps (which I can't think of any), I think this should change; no SIGCHLD trap should be queued while a SIGCHLD trap is already in progress. With this change: diff --git a/trap.c b/trap.c index dd1c9a56..5ce6ab4f 100644 --- a/trap.c +++ b/trap.c @@ -643,6 +643,8 @@ void queue_sigchld_trap (nchild) int nchild; { + if (sigmodes[SIGCHLD] & SIG_INPROGRESS) + return; if (nchild > 0) { catch_flag = 1; bash behaves this way: $ trap uname chld $ uname -sr Linux 5.4.0-66-generic Linux $ uname -sr Linux 5.4.0-66-generic Linux $ and I think this is what average user would expect. Whether there's a better fix is beyond me though.