diff options
author | Chet Ramey <chet.ramey@case.edu> | 2022-12-13 12:42:51 -0500 |
---|---|---|
committer | Chet Ramey <chet.ramey@case.edu> | 2022-12-13 12:42:51 -0500 |
commit | 6647917a43dd987c5564cc20d0943213b39e748b (patch) | |
tree | 4b6082f97fcda0d4c47fd09604f305cb5bb98609 | |
parent | 52f2cda1a2156c8532f2f49391470cf2f66a1bd0 (diff) | |
download | bash-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.c | 1 | ||||
-rw-r--r-- | patchlevel.h | 2 | ||||
-rw-r--r-- | sig.c | 28 |
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_ */ @@ -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 |