bug-bash
[Top][All Lists]
Advanced

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

Re: Bug where SIGINT trap handler isn't called


From: Chet Ramey
Subject: Re: Bug where SIGINT trap handler isn't called
Date: Tue, 21 Jul 2015 22:01:30 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:31.0) Gecko/20100101 Thunderbird/31.6.0

On 7/16/15 12:05 AM, Patrick Plagwitz wrote:

>> This is another case of the scenario most recently described in
>>
>> http://lists.gnu.org/archive/html/bug-bash/2014-03/msg00108.html
>>
>> In this case, python appears to catch the SIGINT (it looks like a
>> KeyboardInterrupt exception), print the message, and exit with status 1.
>>
>> Chet
>>
> 
> Ok, I see.
> However, there appears to be some race condition when waiting for a
> command substitution.
> I have the attached combination of scripts.
> 
> When run with
> $ bash run-until-end-of-loop.sh bash start-subst-loop.sh '2>/dev/null'
> , the script will try to launch and SIGINT subst-loop.sh repeatedly
> until the SIGINT trap is once *not* called which will happen in at most
> 200 repetitions on my machine. The script then ends after printing “end
> of loop”. The python script execute-with-sigint.py is only there to
> enable subst-loop.sh to receive a SIGINT at all.
> subst-loop.sh calls date(1) in a loop; date should have SIGINT set to
> SIG_DFL other than python initially.
> 
> I analyzed the execution by inserting some debug output into the bash
> code. It seems that in the case that the SIGINT trap is not called
> subst-loop.sh gets the SIGINT while (or shortly before or after) calling
> waitpid in waitchld:jobs.c which will then return without errno ==
> EINTR. The wait_sigint_handler will be called, though, and so
> wait_sigint_received will be true.

This doesn't agree with what I see on RHEL6.  I get waitpid() returning -1/
EINTR, which bash interprets, using a heuristic, to mean that the child
blocked or caught SIGINT, in which case bash should not act as if it
received it.

There is a small race condition here, which is very hard to close while
maintaining the desired behavior: bash only responds to SIGINT received
while waiting for a child if the child exits due to SIGINT.  You appear
to have hit it: the timing of the ^C is such that waitpid returns
-1/EINTR, causing the shell to ignore the ^C.  I suspect this is because
the child called exit(0) before the ^C arrived and the shell got the
signal, but the child exited successfully, causing the shell to assume
the child blocked or caught the SIGINT.

That heuristic was developed as the result of an extensive discussion
between me and several Linux kernel developers back in 2011.  You can
read that here:

http://lists.gnu.org/archive/html/bug-bash/2011-02/msg00050.html
http://lists.gnu.org/archive/html/bug-bash/2011-03/msg00000.html

I will look at the signal handler race condition you identified.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU    chet@case.edu    http://cnswww.cns.cwru.edu/~chet/



reply via email to

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