[Top][All Lists]

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

Bug where SIGINT trap handler isn't called

From: Patrick Plagwitz
Subject: Bug where SIGINT trap handler isn't called
Date: Mon, 29 Jun 2015 21:41:07 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu'
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib
-D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe
-fstack-protector-strong --param=ssp-buffer-size=4
-DSTANDARD_UTILS_PATH='/usr/bin' -DSYS_BASHRC='/etc/bash.bashrc'
uname output: Linux PatrickDesktop 3.19.2-1-ARCH #1 SMP PREEMPT Wed Mar
18 16:21:02 CET 2015 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu

Bash Version: 4.3
Patch Level: 39
Release Status: release

There's a bug that happens when waiting for a child process to complete
(via wait_for in jobs.c) that isn't part of a job, like command
substitution subshells. If a SIGINT is caught by the
wait_sigint_handler, the handler sets the wait_sigint_received flag
which is checked in set_job_status_and_cleanup. But
set_job_status_and_cleanup is called from waitchld only if the pid
belongs to a process that is part of a job. The result is that a SIGINT
trap, if it exists, is not called if a SIGINT is received while waiting
for a comsub subshell.

Running the following script (requires python) and giving it a SIGINT
(via ^C) when it blocks doesn't produce any output from the script.
Because SIGINT is trapped it should print “trapped”, however. Closing
stdout causes wait_for to be called in command_substitute:subst.c.

  trap 'echo trapped >&2; exit 1' INT

  foo="$(python -c 'import time, os; os.close(1); time.sleep(20)')"

The attached patch makes a conservative change that moves the code that
calls the SIGINT trap handler from set_job_status_and_cleanup to a new
function handle_sigint_caught_during_wait. This function is then
additionally called from waitchld for dead children that don't belong to
a job.

Related to the code the fix touches: handle_sigint_caught_during_wait
contains some duplicated code. Also, wait_for calls waitchld as long as
the child or job is still running and waitchld and
set_job_status_and_cleanup in turn call handle_sigint_caught_during_wait
if the child or job is dead. This seems to ensure that the SIGINT trap
handler is called at most once for a call to wait_for but isn't wait_for
a better place to check wait_sigint_received after having restored the
sigint handler (restore_sigint_handler()), especially since it already
contains CHECK_WAIT_INTR. Not to mention that a SIGINT could be received
after checking the wait_sigint_received flag and before restoring the
signal handler, as far as I understand it.

Attachment: patch
Description: Text document

reply via email to

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