bug-bash
[Top][All Lists]
Advanced

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

Re: SIGINT handling during async functions


From: Chet Ramey
Subject: Re: SIGINT handling during async functions
Date: Mon, 16 Jan 2023 12:26:18 -0500
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.6.1

On 1/12/23 6:34 PM, Tycho Kirchner wrote:
Hi,
we found quite some inconsistency and weirdness in the handling of SIGINT's during async function calls and were wondering, whether those are expected. All calls were executed from a script with jobcontrol turned off (set +m) while pressing Ctrl+C shortly afterwards.

Thanks for the report. The basic issue is that the process started to
execute the background command (`asynchronous list') does have the
SIGINT and SIGQUIT dispositions set to SIG_IGN, but the processes it
creates don't. The issue is that the processes in this list have to ignore
SIGINT ("the commands in the list shall inherit from the shell a signal
action of ignored (SIG_IGN) for the  SIGINT and SIGQUIT signals" from the
normative standard text) but they have to be allowed to use trap to change
the signal dispositions (POSIX interp 751).

The first problem is that if, say, a shell forked to run the shell function
tries to initialize its signals and finds SIGINT ignored, it will assume
that SIGINT should be `hard ignored', and non-interactive shells are not
allowed to change that ("Signals that were ignored on entry to a non-
interactive shell cannot be trapped or reset"). This is what happens with
the `trap -p' and why the trap seems to change. We had a rousing discussion
about precisely what "on entry" means a few years back.

The second problem is figuring out how to set the SIGINT disposition in
the child, since it's no longer a simple "what did I inherit from my
parent?"

So what do we do about that? Well, you want to preserve the original
disposition of SIGINT in the child process that sets the handler to
SIG_IGN, or figure out a different way that the child process can change
that disposition, so an inherited value of SIG_IGN doesn't prevent a shell
from setting a new trap. You also want to prevent the shell from setting
the SIGINT disposition of processes it forks to this preserved previous
disposition, since they're all supposed to get SIG_IGN by default (but see
below!).

The fix is to add enough state machinery to detect this situation and
behave in a way that can satisfy both the standard and the later
interpretation, while being careful not to undo this work later. This is
obviously not how bash worked in the past.

It gets tricky. Say a shell forked to run this asynchronous list runs trap
to change the SIGINT disposition. It inherited SIG_IGN from its parent, but
now the processes it forks need SIGINT to be set to SIG_DFL instead of
SIG_IGN ("traps caught by the shell shall be set to the default values").
So this new state sort of ripples across different operations.


The main INT handler is never executed in foofunc (is that expected?)

Yes, subshells never inherit traps.

while the new (default) handler either aborts command execution in case of 'foofunc &' or continues execution in case of '{ foofunc; } &'.

Inconsistent handling of the above requirements.

While on 'foofunc &' 'trap -p' at the beginning of foofunc (wrongly) prints the main handler,

That's not wrong; the shell has to preserve the trap strings while changing
the disposition and only change the string if a new trap is set. It's all
very ad-hoc.

 in case of '{ foofunc; } &' it suddenly prints the ignore handler
"trap -- '' SIGINT" and remains indeed uninterruptible. > Thus printing the
trap apparently changes bash's behavior.

Kind of. Reinitializing the signals reveals the real handler, and `trap -p'
just displays it. It's setting SIGINT to be `hard ignored' that is the
problem here.

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




reply via email to

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