bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Fix exit status of signal handlers in shell scripts


From: Dmitry V. Levin
Subject: Re: [PATCH] Fix exit status of signal handlers in shell scripts
Date: Sun, 31 Jan 2010 15:04:01 +0300

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

Attachment: pgpYyqZWh5tLh.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]