bug-gnulib
[Top][All Lists]
Advanced

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

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


From: Dmitry V. Levin
Subject: [PATCH] Fix exit status of signal handlers in shell scripts
Date: Sat, 30 Jan 2010 22:12:01 +0300

Hi,

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:

$ for i in `seq 0 9`; do sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done' & pid=$! && sleep 0.01 && kill -TERM -$pid && wait $pid; done
[1] 5122
Terminated
[1]+  Exit 143                sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5142
Terminated
[1]+  Exit 143                sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5165
[1]+  Exit 1                  sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5201
[1]+  Done                    sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5238
Terminated
[1]+  Exit 143                sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5271
[1]+  Exit 1                  sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5306
Terminated
[1]+  Exit 143                sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5341
Terminated
[1]+  Exit 143                sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5376
[1]+  Done                    sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'
[1] 5411
[1]+  Done                    sh -c 'trap "exit \$?" TERM; while /bin/true; do 
/bin/false; done'

Proposed patch is attached.  It doesn't fix multiple trap bugs in the
test suite, though:
$ grep -r '\<trap[[:space:]].*15' tests/
tests/uniwidth/test-uc_width2.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-vc-list-files-git.sh:trap '(exit $?); exit $?' 1 2 13 15
tests/test-yesno.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-vprintf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-fpending.sh:trap 'rm -fr $tmpfile' 1 2 3 15
tests/test-tsearch.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-xstrtoimax.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-perror.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-fprintf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-select-out.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-binary-io.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-vc-list-files-cvs.sh:trap '(exit $?); exit $?' 1 2 13 15
tests/test-xstrtol.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-dprintf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-xstrtoumax.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-printf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-atexit.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-select-in.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-xprintf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-closein.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-sigpipe.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-update-copyright.sh:trap 'rm -f $TMP_BASE*' 0 1 2 3 15
tests/test-lseek.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-vdprintf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-vfprintf-posix.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-c-stack2.sh:trap 'rm -fr $tmpfiles' 1 2 3 15
tests/test-c-stack.sh:trap 'rm -fr $tmpfiles' 1 2 3 15

What's wrong with these "trap 'rm -fr $tmpfiles' 1 2 3 15" lines?
This signal handler does no process termination thus leaving things in
an inconsistent state.  Proper fix would be to use functions from
tests/init.sh


-- 
ldv

Attachment: gnulib-trap.patch
Description: Text document

Attachment: pgppZ1b4QYOSr.pgp
Description: PGP signature


reply via email to

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