On Sun, Jan 31, 2010 at 08:05:20AM +0100, Ralf Wildenhues wrote: > * Dmitry V. Levin wrote on Sat, Jan 30, 2010 at 08:12:01PM CET: > > There is a comment about shell signal handlers in gnulib-tool saying that > > "The value of $? is 128 + signal number and is set before the > > trap-registered command is run". Unfortunately, this comment is wrong, > > and it seems to be a widespread misunderstanding. > > > > The GNU Autoconf manual says that "it is widely admitted that when > > entering the trap `$?' should be set to the exit status of the last > > command run before the trap." > > > > In case of signal handler, the exit status of the last command run > > before the trap might be 128 + signal number, this usually happens when > > the last command before the trap was a process terminated by signal. In > > other cases, the value of $? may be arbitrary. Sometimes it's quite > > hard to guess this value due to race conditions. Here is an example of > > such race condition where the value of $? takes one of 3 different > > values: 0, 1 and 143: > > Can you please explain whose fault this is? Is that a kernel issue, a > shell issue, or expected behavior given a POSIX system?
It is expected behaviour. > What system and shell (version?) were your tests done on? I tested my example with ash, bash and zsh on a GNU/Linux system. > What are the "other cases" > you mention, where no process was terminated by the signal, but the > signal delivered somewhere nonethess? A moment when the signal can be delivered to the shell process is not necessarily the moment when an external command is executed. The signal can be delivered when a builtin is executed, or even when nothing is executed yet. In this case, the exit status of the last command run before the trap has nothing related to the just delivered signal. Here is another example of race to illustrate the case: $ for i in `seq 0 9`; do sh -c 'trap "exit \$?" TERM; while true; do false; done' & pid=$! && sleep 0.01 && kill -TERM -$pid && wait $pid; done [1] 9770 [1]+ Done sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9772 [1]+ Done sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9774 [1]+ Done sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9776 [1]+ Exit 1 sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9778 [1]+ Done sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9780 [1]+ Exit 1 sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9782 [1]+ Exit 1 sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9784 [1]+ Exit 1 sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9786 [1]+ Done sh -c 'trap "exit \$?" TERM; while true; do false; done' [1] 9788 [1]+ Exit 1 sh -c 'trap "exit \$?" TERM; while true; do false; done' In this example, both "true" and "false" are shell builtins, and no external commands are executed. There are no process to be terminated by signal, so the value of $? on entrance to the trap can be either 0 or 1. -- ldv
pgpAZHO5Y10Yz.pgp
Description: PGP signature