summaryrefslogtreecommitdiffstats
path: root/debian/patches/bash52-014.diff
blob: 5d402e7552dfc74942c4477f62ed427dda8b69e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
			     BASH PATCH REPORT
			     =================

Bash-Release:	5.2
Patch-ID:	bash52-014

Bug-Reported-by:	Andreas Schwab <schwab@suse.de>
Bug-Reference-ID:	<mvmv8opcbha.fsf@suse.de>
Bug-Reference-URL:	https://lists.gnu.org/archive/html/bug-bash/2022-10/msg00076.html

Bug-Description:

Bash defers processing additional terminating signals when running the
EXIT trap while exiting due to a terminating signal. This patch allows the
new terminating signal to kill the shell immediately.

--- 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)
 	    {
--- 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_ */
--- a/sig.c
+++ b/sig.c
@@ -94,6 +94,7 @@ static SigHandler *old_winch = (SigHandl
 #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