Date: Thu, 27 Apr 2017 01:57:48 +0200 From: Vincent Lefevre <vincent-o...@vinc17.net> Message-ID: <20170426235748.ga11...@zira.vinc17.org>
| In such a case, how can you know the number of remaining processes? Background processes, I assume you mean - you cannot, really, the closest things come would be by using the jobs command, or if you happen to know the order they should finish, you can wait on each in turn, something like for pid in M N O P ... do wait $pid # whatever else needs doing done and then you'll know how many have finished. The shell's wait command doesn't allow for other find grained control (as much as it might be nice if it did.) Don't fool yourself into believing that SIGCHLD handling with traps is useful for doing anything much in the shell - it is there because there is a SIHCHLD signal, and processes can catch it, and the trap command allows handling all signals that can be caught. You can trap on SEGV as well, but unless something is sending SEGV signals at the shell (using kill or something) that won't be useful either. But for SIGCHLD, at C level, the general idea is that the handler waits with WNOHANG for as many processes as have exited (and retrieves status of each of them). But the shell wait command has no equiv of WNOHANG, you either wait for a specific process (or job) or for all of them. That means you cannot really implement a SIGCHLD trap handler in (portable) sh that does anything particularly useful. kre ps: the seq command in your example cannot (properly) have caused the SIGCHLD that you (think you) counted, as it is running in a sub-shell, and traps get reset there (and even if they didn't, that would update a different copy of the counter 'c') What you're seeing is the effect of that wait for the subshell to exit, combined with the way that traps are implemented, and processed - the SIGCHLD that is caught that you thought was from seq is not, it is from one or more of the background processes, or the subshell itself (or both of those.) When you enumerate the seq output instead of invoking it in `` (or $()) you are just removing one of the instances where the the trap could get executed. You can see that background processes do generate SIGCHLD with a script like... c=0 trap 'c=$((c + 1))' CHLD while [ $c -lt 3 ]; do echo $c read junk sleep 0.5 & done which has no non-builtin foreground commands (in most shells anyway.) If you start more background sleeps in the loop, you'll see that you still advance by at most 1 (in ash derived shells) per iteration of the loop, though unless you are very fast supplying the input for the "read" you can expect all of the sleeps to finish (which is why you want a sub-second delay ideally).