From: Johannes Altmanninger <aclopte@gmail.com>
To: harald@gigawatt.nl
Cc: aclopte@gmail.com, dash@vger.kernel.org
Subject: [PATCH v2] Allow trap to un-ignore SIGINT in asynchronous subshells
Date: Fri, 29 Mar 2024 12:24:00 +0100 [thread overview]
Message-ID: <20240329112419.1571653-1-aclopte@gmail.com> (raw)
In-Reply-To: <b42dbf13-989d-4609-bbcb-8b9eababbe65@gigawatt.nl>
Unlike in Bash or Zsh, this asynchronous job ignores SIGINT, despite
builtin trap explicitly resetting the SIGINT handler.
dash -c '( trap - INT; sleep inf ) &'
POSIX[*] Section 2.11 on Signals and Error Handling says about
background execution:
> If job control is disabled (see the description of set -m) when
> the shell executes an asynchronous list, the commands in the list
> shall inherit from the shell a signal action of ignored (SIG_IGN)
> for the SIGINT and SIGQUIT signals. In all other cases, commands
> executed by the shell shall inherit the same signal actions as those
> inherited by the shell from its parent unless a signal action is
> modified by the trap special built-in (see trap)
It is not clear to me from this description whether the trap builtin is
supposed to un-ignore SIGINT and SIGQUIT in the above asynchronous job.
I think yes because processes like "sh -c 'trap ...'" can already
do that, so why treat subshells differently. The Bash maintainer
seems to agree when responding to a related bug report[**]
although that one is not about subshells specifically.
> The issue is that the processes in this list have to ignore SIGINT
> [...] but they have to be allowed to use trap to change the signal
> dispositions (POSIX interp 751)
This issue exists because we "hard-ignore" (meaning ignore
permanently) SIGINT and SIGQUIT in backgrounded subshells; I'm
not sure why. Git blame is not helpful since this existed since
the initial Git import. I failed to find a test suite; no luck at
http://www.opengroup.org/testing/testsuites/vscpcts2003.htm where I
get SSL errors.
Since I don't see any reason for hard-ignore logic, remove it
altogether. This means that either of
trap - INT; trap - QUIT
set -i
in a backgrounded subshell will now un-ignore SIGINT and SIGQUIT.
I did not find other behavior changes but maybe there is a good reason
for S_HARD_IGN?
[*]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
[**]: https://lists.gnu.org/archive/html/bug-bash/2023-01/msg00050.html
{{{ Test cases:
shell=src/dash
set -e
SubshellWith() {
parent_pid=$(setsid "$shell" -c "( $1; sleep 99 ) </dev/null >/dev/null 2>&1 & echo \$\$")
sleep 1
subshell_pid=$(ps -o pid= -$parent_pid | tail -n 1)
}
trap 'kill -TERM -$parent_pid 2>/dev//null ||:' EXIT # Tear down after a failure.
echo Scenario 0: '"set -i"' maks a subshell un-ignore SIGINT.
SubshellWith 'set -i'
kill -INT $subshell_pid
! ps -p $subshell_pid | grep sleep || exit 1
kill -TERM -$parent_pid 2>/dev//null ||: # Tear down.
echo Scenario 1: resetting SIGINT handler.
SubshellWith 'trap - INT'
kill -INT -$parent_pid # kill the whole process group since that's the my use case
! ps -p $subshell_pid | grep sleep || exit 1
kill -TERM -$parent_pid 2>/dev//null ||: # Tear down.
echo Scenario 2: ignoring SIGINT.
SubshellWith 'trap "" INT'
kill -INT $subshell_pid
ps -p $subshell_pid | grep sleep || exit 1
kill -TERM -$parent_pid 2>/dev//null ||: # Tear down.
}}}
{{{ Backstory/motivation:
The Kakoune[1] editor likes to run noninteractive shell commands that
boil down to
mkfifo /tmp/fifo
(
trap - INT
make
) >/tmp/fifo 2>&1 &
On Control-C, the editor sends SIGINT to its process group,
which should terminate the subshell running make[2].
We experimented with sending SIGTERM instead but found issues,
specifically if the editor is invoked (without exec) from a wrapper
script, sending SIGTERM to the whole process group would kill the
wrapper script, which in turn makes it send SIGTERM to the editor,
which then terminates.
[1]: https://kakoune.org/
[2]: https://lists.sr.ht/~mawww/kakoune/%3C20240307135831.1967826-3-aclopte@gmail.com%3E
}}}
---
src/trap.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/src/trap.c b/src/trap.c
index cd84814..d80fdde 100644
--- a/src/trap.c
+++ b/src/trap.c
@@ -55,14 +55,12 @@
/*
* Sigmode records the current value of the signal handlers for the various
* modes. A value of zero means that the current handler is not known.
- * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
*/
#define S_DFL 1 /* default signal handling (SIG_DFL) */
#define S_CATCH 2 /* signal is caught */
#define S_IGN 3 /* signal is ignored (SIG_IGN) */
-#define S_HARD_IGN 4 /* signal is ignored permenantly */
-#define S_RESET 5 /* temporary - to reset a hard ignored sig */
+#define S_RESET 4 /* temporary - to reset an ignored sig */
/* trap handler commands */
@@ -233,16 +231,12 @@ setsignal(int signo)
return;
}
if (act.sa_handler == SIG_IGN) {
- if (mflag && (signo == SIGTSTP ||
- signo == SIGTTIN || signo == SIGTTOU)) {
- tsig = S_IGN; /* don't hard ignore these */
- } else
- tsig = S_HARD_IGN;
+ tsig = S_IGN;
} else {
tsig = S_RESET; /* force to be set */
}
}
- if (tsig == S_HARD_IGN || tsig == action)
+ if (tsig == action)
return;
switch (action) {
case S_CATCH:
@@ -268,11 +262,11 @@ setsignal(int signo)
void
ignoresig(int signo)
{
- if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+ if (sigmode[signo - 1] != S_IGN) {
signal(signo, SIG_IGN);
}
if (!vforked)
- sigmode[signo - 1] = S_HARD_IGN;
+ sigmode[signo - 1] = S_IGN;
}
--
2.44.0.368.gc75fd8d815
next prev parent reply other threads:[~2024-03-29 11:24 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-08 11:01 [RFC PATCH] Allow trap to override permanently-ignored signals in background shells Johannes Altmanninger
2024-03-08 11:48 ` Harald van Dijk
2024-03-29 11:24 ` Johannes Altmanninger [this message]
2024-03-29 13:50 ` [PATCH v2] Allow trap to un-ignore SIGINT in asynchronous subshells Jilles Tjoelker
2024-03-29 15:02 ` Johannes Altmanninger
2024-03-29 15:39 ` [PATCH v3] Allow trap to un-ignore SIGINT/SIGQUIT in async subshells Johannes Altmanninger
2024-04-07 11:18 ` Herbert Xu
2024-05-18 8:38 ` [PATCH v4] " Johannes Altmanninger
2024-05-26 10:27 ` Herbert Xu
2024-05-18 8:43 ` [PATCH v3] " Johannes Altmanninger
2024-05-18 9:02 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240329112419.1571653-1-aclopte@gmail.com \
--to=aclopte@gmail.com \
--cc=dash@vger.kernel.org \
--cc=harald@gigawatt.nl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox