[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Provide shopt -s no_async_sig_ignore
From: |
Ian Jackson |
Subject: |
[PATCH] Provide shopt -s no_async_sig_ignore |
Date: |
Tue, 13 Oct 2015 18:26:07 +0100 |
This option disables the standards-mandated resetting of SIGINT (and
QUIT) to SIG_IGN in asynchronous children.
This resetting makes it very hard to write a bash script which invokes
a number of subprocesses in parallel and collects the output. The
problem is that if you ^C the script, the subprocesses carry on
running (doing needless work and perhaps causing lossage).
Working around this in a race-free way with additional code in the
script is very hard indeed. However, we can provide an option to do
the right thing in modern programs.
(The reason for SIGINT being ignored is purely historical: back in the
dawn of time, there was no job control. If you interactively spawned
a background process with &, you wouldn't want your attempts to ^C
your foreground process to kill it. This SIGINT-ignoring also applied
to noninteractive shells and of course came to be relied on. So it is
too late to change the default.)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
CC: Ian Campbell <ian.campbell@citrix.com>
---
MANIFEST | 3 +++
builtins/shopt.def | 2 ++
doc/bash.1 | 10 ++++++++++
doc/bashref.texi | 13 ++++++++++++-
execute_cmd.c | 5 ++++-
tests/asyncsigint.right | 6 ++++++
tests/asyncsigint.tests | 27 +++++++++++++++++++++++++++
tests/run-asyncsigint | 2 ++
tests/shopt.right | 3 +++
9 files changed, 69 insertions(+), 2 deletions(-)
create mode 100644 tests/asyncsigint.right
create mode 100644 tests/asyncsigint.tests
create mode 100644 tests/run-asyncsigint
diff --git a/MANIFEST b/MANIFEST
index 55c8d1c..1c3106c 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -841,6 +841,8 @@ tests/assoc4.sub f
tests/assoc5.sub f
tests/assoc6.sub f
tests/assoc7.sub f
+tests/asyncsigint.tests f
+tests/asyncsigint.right f
tests/braces.tests f
tests/braces.right f
tests/builtins.tests f
@@ -1107,6 +1109,7 @@ tests/run-arith f
tests/run-array f
tests/run-array2 f
tests/run-assoc f
+tests/run-asyncsigint f
tests/run-braces f
tests/run-builtins f
tests/run-case f
diff --git a/builtins/shopt.def b/builtins/shopt.def
index 6050a14..89a9aae 100644
--- a/builtins/shopt.def
+++ b/builtins/shopt.def
@@ -90,6 +90,7 @@ extern int autocd;
extern int glob_star;
extern int glob_asciirange;
extern int lastpipe_opt;
+extern int no_async_sig_ignore_opt;
#if defined (EXTENDED_GLOB)
extern int extended_glob;
@@ -199,6 +200,7 @@ static struct {
#endif
{ "login_shell", &shopt_login_shell, set_login_shell },
{ "mailwarn", &mail_warning, (shopt_set_func_t *)NULL },
+ { "no_async_sig_ignore", &no_async_sig_ignore_opt, (shopt_set_func_t *)NULL
},
#if defined (READLINE)
{ "no_empty_cmd_completion", &no_empty_command_completion, (shopt_set_func_t
*)NULL },
#endif
diff --git a/doc/bash.1 b/doc/bash.1
index 2b1ca15b..f318ab1 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -9535,6 +9535,16 @@ If set, and a file that \fBbash\fP is checking for mail
has been
accessed since the last time it was checked, the message ``The mail in
\fImailfile\fP has been read'' is displayed.
.TP 8
+.B no_async_sig_ignore
+If set in a noninteractive shell, asynchronous commands will
+not have
+.B SIGINT
+and
+.BR SIGQUIT
+ignored;
+instead, those signals' handlers will be reset to those
+inherited by the shell from its parent, as for other signals.
+.TP 8
.B no_empty_cmd_completion
If set, and
.B readline
diff --git a/doc/bashref.texi b/doc/bashref.texi
index 597274b..2556b60 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -3060,7 +3060,10 @@ Non-builtin commands started by Bash have signal
handlers set to the
values inherited by the shell from its parent.
When job control is not in effect, asynchronous commands
ignore @code{SIGINT} and @code{SIGQUIT} in addition to these inherited
-handlers.
+handlers,
+unless the shell option @code{no_async_sig_ignore}
+(see the description of @code{shopt} in @ref{The Shopt Builtin})
+is enabled.
Commands run as a result of
command substitution ignore the keyboard-generated job control signals
@code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
@@ -5146,6 +5149,14 @@ If set, and a file that Bash is checking for mail has
been
accessed since the last time it was checked, the message
@code{"The mail in @var{mailfile} has been read"} is displayed.
+@item no_async_sig_ignore
+If set in a noninteractive shell, asynchronous commands will not
+have
+@code{SIGINT} and @code{SIGQUIT}
+ignored;
+instead, those signals' handlers will be reset to those
+inherited by the shell from its parent, as for other signals.
+
@item no_empty_cmd_completion
If set, and Readline is being used, Bash will not attempt to search
the @env{PATH} for possible completions when completion is attempted
diff --git a/execute_cmd.c b/execute_cmd.c
index 9cebaef..c3b30b6 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -287,6 +287,7 @@ int funcnest = 0;
int funcnest_max = 0; /* bash-4.2 */
int lastpipe_opt = 0;
+int no_async_sig_ignore_opt = 0;
struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
@@ -4827,7 +4828,9 @@ setup_async_signals ()
#endif
#if defined (JOB_CONTROL)
- if (job_control == 0)
+ if (no_async_sig_ignore_opt == 0 && job_control == 0)
+#else
+ if (no_async_sig_ignore_opt == 0)
#endif
{
/* Make sure we get the original signal dispositions now so we don't
diff --git a/tests/asyncsigint.right b/tests/asyncsigint.right
new file mode 100644
index 0000000..0113480
--- /dev/null
+++ b/tests/asyncsigint.right
@@ -0,0 +1,6 @@
+killing
+ 0 0 0
+0
+killing
+130
+trapped-sigint
diff --git a/tests/asyncsigint.tests b/tests/asyncsigint.tests
new file mode 100644
index 0000000..ac0ee79
--- /dev/null
+++ b/tests/asyncsigint.tests
@@ -0,0 +1,27 @@
+: ${TMPDIR:=/tmp}
+
+rc=16
+trap 'echo trapped-sigint; exit $rc' INT
+
+p=$TMPDIR/asyncsigint-rendezvous
+
+runtest () {
+ rm -f $p
+ mkfifo -m 600 $p
+ wc <$p &
+ exec 3>$p
+ echo killing
+ kill -INT $!
+ exec 3>&-
+ wait $!
+ echo $?
+}
+
+runtest
+
+shopt -s no_async_sig_ignore
+
+runtest
+
+rc=0
+kill -INT $$
diff --git a/tests/run-asyncsigint b/tests/run-asyncsigint
new file mode 100644
index 0000000..a2baf9a
--- /dev/null
+++ b/tests/run-asyncsigint
@@ -0,0 +1,2 @@
+${THIS_SH} ./asyncsigint.tests > /tmp/xx 2>&1
+diff /tmp/xx asyncsigint.right && rm -f /tmp/xx
diff --git a/tests/shopt.right b/tests/shopt.right
index 0a7edfb..ba54b73 100644
--- a/tests/shopt.right
+++ b/tests/shopt.right
@@ -37,6 +37,7 @@ shopt -u lastpipe
shopt -u lithist
shopt -u login_shell
shopt -u mailwarn
+shopt -u no_async_sig_ignore
shopt -u no_empty_cmd_completion
shopt -u nocaseglob
shopt -u nocasematch
@@ -92,6 +93,7 @@ shopt -u lastpipe
shopt -u lithist
shopt -u login_shell
shopt -u mailwarn
+shopt -u no_async_sig_ignore
shopt -u no_empty_cmd_completion
shopt -u nocaseglob
shopt -u nocasematch
@@ -128,6 +130,7 @@ lastpipe off
lithist off
login_shell off
mailwarn off
+no_async_sig_ignore off
no_empty_cmd_completion off
nocaseglob off
nocasematch off
--
2.1.4