summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2008-08-01 13:53:43 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2008-08-01 13:53:43 +0000
commit506d73299cd5559b4d303260f2f05901886c937a (patch)
tree3333c417cb5813457fd8c7d5d4eeadfda4f42240
parent5e7e797ca90cd1c1b7ab54d39118f0b7469f348f (diff)
downloadzsh-506d73299cd5559b4d303260f2f05901886c937a.tar.gz
zsh-506d73299cd5559b4d303260f2f05901886c937a.tar.xz
zsh-506d73299cd5559b4d303260f2f05901886c937a.zip
fix problems with trapreturn, in particular in source inside trap
-rw-r--r--ChangeLog4
-rw-r--r--Src/exec.c18
-rw-r--r--Src/init.c2
-rw-r--r--Src/signals.c2
4 files changed, 24 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index b08f66ba0..6f58a36d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2008-08-01  Peter Stephenson  <pws@csr.com>
 
+	* 25367: Src/exec.c, Src/init.c, Src/signals.c: bug with
+	trapreturn in a sourced file caused early return of parent;
+	add protection for nested traps; document trapreturn.
+
 	* unposted: Functions/Misc/add-zsh-hook: testing for existence
 	of hook function when hook was already defined was broken.
 
diff --git a/Src/exec.c b/Src/exec.c
index 8edbf1dc9..daa7ba55c 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -64,7 +64,23 @@ int nohistsave;
 /**/
 mod_export int errflag;
  
-/* Status of return from a trap */
+/*
+ * Status of return from a trap.
+ * This is only active if we are inside a trap, else its value
+ * is irrelevant.  It is initialised to -1 for a function trap and
+ * -2 for a non-function trap and if negative is decremented as
+ * we go deeper into functions and incremented as we come back up.
+ * The value is used to decide if an explicit "return" should cause
+ * a return from the caller of the trap; it does this by setting
+ * trapreturn to a status (i.e. a non-negative value).
+ *
+ * In summary, trapreturn is
+ * - zero unless we are in a trap
+ * - negative in a trap unless it has triggered.  Code uses this
+ *   to detect an active trap.
+ * - non-negative in a trap once it was triggered.  It should remain
+ *   non-negative until restored after execution of the trap.
+ */
  
 /**/
 int trapreturn;
diff --git a/Src/init.c b/Src/init.c
index cf6164321..fcbf9236c 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -191,7 +191,7 @@ loop(int toplevel, int justonce)
 	    exit(lastval);
 	if (((!interact || sourcelevel) && errflag) || retflag)
 	    break;
-	if (trapreturn) {
+	if (trapreturn >= 0) {
 	    lastval = trapreturn;
 	    trapreturn = 0;
 	}
diff --git a/Src/signals.c b/Src/signals.c
index 022ee8fb5..61fff64a2 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -1085,6 +1085,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
     int trapret = 0;
     int obreaks = breaks;
     int oretflag = retflag;
+    int otrapreturn = trapreturn;
     int isfunc;
     int traperr;
 
@@ -1183,6 +1184,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
 	trapret = trapreturn + 1;
     }
     traperr = errflag;
+    trapreturn = otrapreturn;
     execrestore();
     lexrestore();