Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zsh-4.1.1 and trap '...' DEBUG: a bug or a feature?



Peter Stephenson wrote:
> I've noticed that we always queue signals when running traps.  This
> implies ordinary traps (i.e not ZERR, DEBUG, EXIT) are never run inside
> one another.  We could extend this to all traps, but it's not
> necessarily convenient all the time.

Actually, that's not true: we only queue signals when removing traps.
We mark individual traps as ignored when executing traps for them.
(Presumably this means we can not execute one trap per signal.)

However, not executing special traps inside other special traps is still
easy to do.

Index: Doc/Zsh/builtins.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/builtins.yo,v
retrieving revision 1.65
diff -u -r1.65 builtins.yo
--- Doc/Zsh/builtins.yo	24 Sep 2003 14:55:32 -0000	1.65
+++ Doc/Zsh/builtins.yo	24 Mar 2004 12:15:13 -0000
@@ -1116,6 +1116,8 @@
 and the tt(trap) statement is not executed inside the body of a function,
 then the command var(arg) is executed when the shell terminates.
 
+tt(ZERR), tt(DEBUG) and tt(EXIT) traps are not executed inside other traps.
+
 The tt(trap) command with no arguments prints a list of commands
 associated with each signal.
 
Index: Src/signals.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/signals.c,v
retrieving revision 1.24
diff -u -r1.24 signals.c
--- Src/signals.c	10 Mar 2004 10:50:02 -0000	1.24
+++ Src/signals.c	24 Mar 2004 12:15:14 -0000
@@ -932,7 +932,10 @@
     int trapret = 0;
     int obreaks = breaks;
     int isfunc;
- 
+
+    /* Are we already executing a trap? */
+    static int intrap;
+
     /* if signal is being ignored or the trap function		      *
      * is NULL, then return					      *
      *								      *
@@ -946,6 +949,24 @@
     if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
         return;
 
+    /*
+     * Never execute special (synchronous) traps inside other traps.
+     * This can cause unexpected code execution when more than one
+     * of these is set.
+     *
+     * The down side is that it's harder to debug traps.  I don't think
+     * that's a big issue.
+     */
+    if (intrap) {
+	switch (sig) {
+	case SIGEXIT:
+	case SIGDEBUG:
+	case SIGZERR:
+	    return;
+	}
+    }
+
+    intrap++;
     *sigtr |= ZSIG_IGNORED;
 
     lexsave();
@@ -1023,6 +1044,7 @@
 
     if (*sigtr != ZSIG_IGNORED)
 	*sigtr &= ~ZSIG_IGNORED;
+    intrap--;
 }
 
 /* Standard call to execute a trap for a given signal. */

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************



Messages sorted by: Reverse Date, Date, Thread, Author