summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2022-12-13 12:42:51 -0500
committerChet Ramey <chet.ramey@case.edu>2022-12-13 12:42:51 -0500
commit6647917a43dd987c5564cc20d0943213b39e748b (patch)
tree4b6082f97fcda0d4c47fd09604f305cb5bb98609
parent52f2cda1a2156c8532f2f49391470cf2f66a1bd0 (diff)
downloadbash-6647917a43dd987c5564cc20d0943213b39e748b.tar.gz
Bash-5.2 patch 14: process additional terminating signals when running the EXIT trap after a terminating signal
-rw-r--r--execute_cmd.c1
-rw-r--r--patchlevel.h2
-rw-r--r--sig.c28
3 files changed, 25 insertions, 6 deletions
diff --git a/execute_cmd.c b/execute_cmd.c
index 80274162..ee0ea8c4 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -3624,6 +3624,7 @@ execute_case_command (case_command)
free (pattern);
dispose_words (es);
+ QUIT;
if (match)
{
diff --git a/patchlevel.h b/patchlevel.h
index 7ebe846a..d732c90d 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
-#define PATCHLEVEL 13
+#define PATCHLEVEL 14
#endif /* _PATCHLEVEL_H_ */
diff --git a/sig.c b/sig.c
index 840d5775..78980aac 100644
--- a/sig.c
+++ b/sig.c
@@ -94,6 +94,7 @@ static SigHandler *old_winch = (SigHandler *)SIG_DFL;
#endif
static void initialize_shell_signals PARAMS((void));
+static void kill_shell PARAMS((int));
void
initialize_signals (reinit)
@@ -486,6 +487,8 @@ restore_sigmask ()
#endif
}
+static int handling_termsig = 0;
+
sighandler
termsig_sighandler (sig)
int sig;
@@ -532,6 +535,14 @@ termsig_sighandler (sig)
sig == terminating_signal)
terminate_immediately = 1;
+ /* If we are currently handling a terminating signal, we have a couple of
+ choices here. We can ignore this second terminating signal and let the
+ shell exit from the first one, or we can exit immediately by killing
+ the shell with this signal. This code implements the latter; to implement
+ the former, replace the kill_shell(sig) with return. */
+ if (handling_termsig)
+ kill_shell (sig); /* just short-circuit now */
+
terminating_signal = sig;
if (terminate_immediately)
@@ -564,16 +575,13 @@ void
termsig_handler (sig)
int sig;
{
- static int handling_termsig = 0;
- int i, core;
- sigset_t mask;
-
/* Simple semaphore to keep this function from being executed multiple
times. Since we no longer are running as a signal handler, we don't
block multiple occurrences of the terminating signals while running. */
if (handling_termsig)
return;
- handling_termsig = 1;
+
+ handling_termsig = terminating_signal; /* for termsig_sighandler */
terminating_signal = 0; /* keep macro from re-testing true. */
/* I don't believe this condition ever tests true. */
@@ -613,6 +621,16 @@ termsig_handler (sig)
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
+ kill_shell (sig);
+}
+
+static void
+kill_shell (sig)
+ int sig;
+{
+ int i, core;
+ sigset_t mask;
+
/* We don't change the set of blocked signals. If a user starts the shell
with a terminating signal blocked, we won't get here (and if by some
magic chance we do, we'll exit below). What we do is to restore the