bug-bash
[Top][All Lists]
Advanced

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

Re: Signal ignore flags unexpectedly reset after "trap ... EXIT"


From: Chet Ramey
Subject: Re: Signal ignore flags unexpectedly reset after "trap ... EXIT"
Date: Wed, 30 Oct 2019 14:50:50 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:60.0) Gecko/20100101 Thunderbird/60.9.0

On 10/18/19 10:49 AM, Isaac To wrote:
> Dear Chet,
> 
> I read your reply in the mailing list archive.  Thanks a lot for the
> explanation, I get much better ideas about what the shell wants to do for
> me after reading it.  Sorry that I have to reply to my own message rather
> than yours.  I'll subscribe to the mailing list to ensure that this is not
> needed any more.
> 
> Reading your response carefully I think you get most of the things you say
> you didn't get.  For others, I want to add one comment:
> 
>> trap '' USR1
>>> grep SigIgn /proc/$BASHPID/status
>>
>> Presumably this reflects it; I don't know how to interpret the output.
>>
> 
> This is a bitmask containing ignored signals, where signal n is represented
> by value (1 << (n - 1)).  The 200 is signal 10, i.e., USR1.
> 
> Then I want to explain what I consider a bug:
> 
>> (
>>>     echo subshell $BASHPID
>>>     grep SigIgn /proc/$BASHPID/status
>>
>> After setting all the caught signals back to SIG_DFL, this shell, call it
>> pid 811, sets SIGUSR1 to SIG_IGN, since that is the disposition it had when
>> its parent was started. This happens before pretty much anything else.
>> ...
>> Let's say this process has pid 813. In this subshell, there shouldn't be
>> any ignored signals after the shell initializes (it's interactive), but it
>> does this lazily.
>>
> 
> If it should be set to SIG_DFL once anything about signals have to be done,
> why it even attempt to reset it to SIG_IGN after the subshell initialize?
> And, I cannot say that bringing an ignored signal back alive in the name of
> "exit handling" is a "correct behavior"...

Posix says two things: that a (...) subshell should start with signal
dispositions that are either SIG_DFL or SIG_IGN (if the signal was ignored
when the shell creating the subshell was started or when the subshell was
created) and that an interactive shell doesn't have to keep signals that
were set to SIG_IGN at startup ignored. Interactive shells can do pretty
much what they want with signal handlers.

>> I get exactly the same results in bash-4.4 running on RHEL7.
>>
> 
> I'd like to confirm your results: when I run it once again in my Ubuntu 18
> with bash 4.4 I see the same results.  After reading your messages I can do
> simpler checks of the behaviour.  First, I test 3 different versions of
> bash by running:
> 
>    - A: Ubuntu 19.04, bash 5.0.3(1)-release
>    - B: Debian 4.9.189-3, bash 4.4.12(1)-release (Same results on 4.4.20 of
>    Ubuntu 18.04.3)
>    - C: CentOS Linux release 7.7.1908, bash 4.2.46(2)-release
> 
> Here are the tests:
> 
> $ trap '' USR1
> $ (trap true EXIT; grep Ign /proc/$BASHPID/status)
> 
> I see:
> 
> A: SigIgn: 0000000000000200
> B: SigIgn: 0000000000000200
> C: SigIgn: 0000000000000200
> 
> So it is not that within subshells of interactive shells, once you trap
> EXIT you get the signal handler reset.  In all the above cases it didn't
> happen.

Yes, you're right. I skewed the results in my example by running `trap'
without arguments in the subshell to view the trap dispositions. That
was my addition, not in your original script.

> 
> Then I test it by running:
> 
> $ trap '' USR1
> $ (trap true EXIT; (grep Ign /proc/$BASHPID/status) )
> 
> For this, I get:
> 
> A: SigIgn: 0000000000000200
> B: SigIgn: 0000000000000200
> C: SigIgn: 0000000000000000
> 
> This is the actual reason why I have my complex test case in the previous
> mail: in my deployment there is an error, and I go back to a convenient
> machine running like (C) and try to reproduce it.  I suddenly end up with
> something that causes an error.

This appears to have been a bug in bash-4.2, which is many years old. The
idea is that the subshell needs to run with USR1 ignored because it is
ignored in the parent. So the subshell forks, it inherits the SIG_IGN
disposition, and nothing changes the SIGUSR1 disposition after the subshell
starts, so it remains ignored.

If I can recall correctly, the change came after a long posix group
discussion back in 2013 about exactly what the words "at shell startup"
and "on entry to the shell" mean.

> 
> Then here is what is inspired by your reply:
> 
> $ trap '' USR1
> $ bash
> $ (trap true EXIT; grep Ign /proc/$BASHPID/status)
> 
> For this:
> 
> A: SigIgn: 0000000000000000
> B: SigIgn: 0000000000000000
> C: SigIgn: 0000000000000200
> 
> This is the behaviour I was reporting.  The thing is, the behaviour is
> undocumented, and even if you want to document it you don't know how to do
> so.

Starting the interactive shell permits bash to reset ignored signals to
SIG_DFL or catch them. Posix says

"An interactive shell may reset or catch signals ignored on entry."

and bash does so. This is where the subshell knowing it's part of an
interactive shell when it sets the EXIT trap becomes relevant. If you
want to look at the code, look at initialize_terminating_signals()
and the places in trap.c that call it when setting the EXIT trap.

The sequence is as follows: the interactive shell starts, notes that
SIGUSR1 was set to SIG_IGN at startup, and catches SIGUSR1. The subshell
forks, the SIGUSR1 signal gets set to SIG_IGN (because it was ignored
at the interactive shell's startup) and runs trap to set the EXIT trap.
The trap command notes that it's running as part of an interactive shell
and catches the fatal signals (including SIGUSR1) so it can run the exit
trap before the shell exits, as required.

This is pretty much what was in my previous message. I don't consider it
a bug.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    address@hidden    http://tiswww.cwru.edu/~chet/



reply via email to

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