bug-bash
[Top][All Lists]
Advanced

[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




reply via email to

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