about summary refs log tree commit diff
path: root/Src/builtin.c
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2017-04-27 18:56:18 +0100
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2017-04-27 18:56:18 +0100
commitd7110d8f01cae8c8d51c7abd0255f533cd8b8623 (patch)
tree238931229fcf7831c7ff5f41212f9626167fbb63 /Src/builtin.c
parent48b0daf3d4972987873f1be00cc73d73734daf05 (diff)
downloadzsh-d7110d8f01cae8c8d51c7abd0255f533cd8b8623.tar.gz
zsh-d7110d8f01cae8c8d51c7abd0255f533cd8b8623.tar.xz
zsh-d7110d8f01cae8c8d51c7abd0255f533cd8b8623.zip
41012: Fix premature exit from nested function in EXIT trap.
Also add check so we don't delay an exit if we were already in
an EXIT trap for the main shell, as we should in that case leave
immediately.
Diffstat (limited to 'Src/builtin.c')
-rw-r--r--Src/builtin.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/Src/builtin.c b/Src/builtin.c
index b2e552db7..063644efb 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -5500,7 +5500,7 @@ bin_break(char *name, char **argv, UNUSED(Options ops), int func)
 	}
 	/*FALLTHROUGH*/
     case BIN_EXIT:
-	if (locallevel > forklevel) {
+	if (locallevel > forklevel && shell_exiting != -1) {
 	    /*
 	     * We don't exit directly from functions to allow tidying
 	     * up, in particular EXIT traps.  We still need to perform
@@ -5509,6 +5509,9 @@ bin_break(char *name, char **argv, UNUSED(Options ops), int func)
 	     *
 	     * If we are forked, we exit the shell at the function depth
 	     * at which we became a subshell, hence the comparison.
+	     *
+	     * If we are already exiting... give this all up as
+	     * a bad job.
 	     */
 	    if (stopmsg || (zexit(0,2), !stopmsg)) {
 		retflag = 1;
@@ -5555,6 +5558,14 @@ checkjobs(void)
     }
 }
 
+/*
+ * -1 if the shell is already committed to exit.
+ * positive if zexit() was already called.
+ */
+
+/**/
+int shell_exiting;
+
 /* exit the shell.  val is the return value of the shell.  *
  * from_where is
  *   1   if zexit is called because of a signal
@@ -5566,10 +5577,8 @@ checkjobs(void)
 mod_export void
 zexit(int val, int from_where)
 {
-    static int in_exit;
-
     /* Don't do anything recursively:  see below */
-    if (in_exit == -1)
+    if (shell_exiting == -1)
 	return;
 
     if (isset(MONITOR) && !stopmsg && from_where != 1) {
@@ -5582,14 +5591,14 @@ zexit(int val, int from_where)
 	}
     }
     /* Positive in_exit means we have been here before */
-    if (from_where == 2 || (in_exit++ && from_where))
+    if (from_where == 2 || (shell_exiting++ && from_where))
 	return;
 
     /*
-     * We're now committed to exiting.  Set in_exit to -1 to
+     * We're now committed to exiting.  Set shell_exiting to -1 to
      * indicate we shouldn't do any recursive processing.
      */
-    in_exit = -1;
+    shell_exiting = -1;
     /*
      * We want to do all remaining processing regardless of preceding
      * errors, even user interrupts.