zsh-workers
 help / color / mirror / code / Atom feed
* zsh-4.1.1 and trap '...' DEBUG: a bug or a feature?
@ 2004-03-23 17:54 Nelson H. F. Beebe
  2004-03-23 18:20 ` Wayne Davison
  2004-03-23 18:49 ` Peter Stephenson
  0 siblings, 2 replies; 4+ messages in thread
From: Nelson H. F. Beebe @ 2004-03-23 17:54 UTC (permalink / raw)
  To: zsh-workers; +Cc: beebe

We are finishing up a book on shell programming, and in the course of
documenting the handling of DEBUG traps, I found unexpected behavior
in zsh-4.1.1, which I have installed on about 20 flavors of Unix at my
site.

Consider the following test file:

	% cat debug-trap
	trap 'echo This is an EXIT trap' EXIT
	trap 'echo This is a DEBUG trap' DEBUG
	pwd
	pwd
	pwd
	pwd

Now watch this behavior (recorded on an IA-64 system, unless otherwise
noted).

First, bash:

	% /local/build/icc/bash-2.05b.p7/bash --version
	GNU bash, version 2.05b.0(1)-release (ia64-unknown-linux-gnu)

	# That is the latest bash version 2.05b with all 7 released patches installed

	% /local/build/icc/bash-2.05b.p7/bash debug-trap
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	This is an EXIT trap

Tests showed that the bash behavior depends critically on the patch
level; I'm in the process of upgrading my systems to have 2.05b with
all 7 patches.

Next zsh-4.1.1 (the latest):

	% zsh debug-trap
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	/tmp
	This is a DEBUG trap
	This is an EXIT trap
	This is a DEBUG trap

Notice that zsh takes one final DEBUG trap that bash does not.  That
seems undesirable, because the EXIT trap code is documented in sh and
ksh to be the last code executed, and is invoked in response to either
normal termination, or an explicit exit statement.

Is this a bug, or a feature?

>From the zsh manual in the info system, I found this paragraph:

     If SIG is ZERR then ARG will be executed after each command with a
     nonzero exit status.  If SIG is DEBUG then ARG will be executed
     after each command.  If SIG is 0 or EXIT and the trap statement is
     executed inside the body of a function, then the command ARG is
     executed after the function completes.  If SIG is 0 or EXIT and
     the trap statement is not executed inside the body of a function,
     then the command ARG is executed when the shell terminates.

The last sentence implies that it is a feature, but perhaps it should
be reconsidered, and made to do what bash and ksh93 do, or else an
explanation should be offered in the manual of why a different choice
was made. Remember, unnecessary implementation differences create
portability headaches, and make life hard for documenters and authors
who have to explain, or even defend, the differences to their readers.

I checked that the extra invocation of the DEBUG trap does not spoil
the intended exit code:

	% cat exit.sh
	#! /bin/sh
	trap "ls -l $0; echo 'Check the exit status: it should be 49.'" EXIT
	trap "echo This is a DEBUG trap" DEBUG

	echo Leaving $0 with exit code 49
	exit 49

	% zsh ./exit.sh
	This is a DEBUG trap
	Leaving ./exit.sh with exit code 49
	This is a DEBUG trap
	-rwxrwxr-x  1 beebe staff 162 Mar 23 10:44 ./exit.sh
	This is a DEBUG trap
	Check the exit status: it should be 49.
	This is a DEBUG trap

	% echo $?
	49

POSIX (IEEE Std 1003.1-2001) does not include the DEBUG trap, so there
is no independent guidance there.

-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- University of Utah                    FAX: +1 801 581 4148                  -
- Department of Mathematics, 110 LCB    Internet e-mail: beebe@math.utah.edu  -
- 155 S 1400 E RM 233                       beebe@acm.org  beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe  -
-------------------------------------------------------------------------------


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: zsh-4.1.1 and trap '...' DEBUG: a bug or a feature?
  2004-03-23 17:54 zsh-4.1.1 and trap '...' DEBUG: a bug or a feature? Nelson H. F. Beebe
@ 2004-03-23 18:20 ` Wayne Davison
  2004-03-23 18:49 ` Peter Stephenson
  1 sibling, 0 replies; 4+ messages in thread
From: Wayne Davison @ 2004-03-23 18:20 UTC (permalink / raw)
  To: Nelson H. F. Beebe; +Cc: zsh-workers

On Tue, Mar 23, 2004 at 10:54:22AM -0700, Nelson H. F. Beebe wrote:
> Notice that zsh takes one final DEBUG trap that bash does not.

This is because your EXIT trap had one command in it.  If it had two
commands, you would have seen two final DEBUG trap executions.  One
way to avoid this is to turn off DEBUG in the exit trap:

trap 'trap - DEBUG; echo This is an EXIT trap' EXIT
trap 'echo This is a DEBUG trap' DEBUG
pwd
pwd
pwd
pwd

That would duplicate the bash behavior you saw.  However, I don't know
if this is proper POSIX behavior or not.

..wayne..


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: zsh-4.1.1 and trap '...' DEBUG: a bug or a feature?
  2004-03-23 17:54 zsh-4.1.1 and trap '...' DEBUG: a bug or a feature? Nelson H. F. Beebe
  2004-03-23 18:20 ` Wayne Davison
@ 2004-03-23 18:49 ` Peter Stephenson
  2004-03-24 12:29   ` Peter Stephenson
  1 sibling, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2004-03-23 18:49 UTC (permalink / raw)
  To: Nelson H. F. Beebe, Zsh hackers list

"Nelson H. F. Beebe" wrote:
> We are finishing up a book on shell programming, 

Oh, you too.  (Actually, ours isn't really on programming, it's on
command-line usage.)

> 	% cat debug-trap
> 	trap 'echo This is an EXIT trap' EXIT
> 	trap 'echo This is a DEBUG trap' DEBUG
> 	pwd
> 	pwd
> 	pwd
> 	pwd
> 
> Next zsh-4.1.1 (the latest):
> 
> 	% zsh debug-trap
> 	This is a DEBUG trap
> 	/tmp
> 	This is a DEBUG trap
> 	/tmp
> 	This is a DEBUG trap
> 	/tmp
> 	This is a DEBUG trap
> 	/tmp
> 	This is a DEBUG trap
> 	This is an EXIT trap
> 	This is a DEBUG trap
> 
> Notice that zsh takes one final DEBUG trap that bash does not.
> 
> Is this a bug, or a feature?

Strictly, it's not a bug, as you saw from the docs.  The extra DEBUG is
running when the code in the EXIT trap is run.  There is (necessarily)
code to prevent recursive running of traps, but it does not extend to
different traps.

However, we can redocument our way out of it --- I would guess no one is
relying on this behaviour.  I don't think the current behaviour is
desirable.

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.

The other obvious possibilities are not running other traps only inside
EXIT traps, or not running DEBUG traps inside other traps.  There are
also sorts of permutations.

I have't had time to look at how bash and ksh handle these possibilities.

-- 
Peter Stephenson <pws@csr.com>                  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
**********************************************************************


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: zsh-4.1.1 and trap '...' DEBUG: a bug or a feature?
  2004-03-23 18:49 ` Peter Stephenson
@ 2004-03-24 12:29   ` Peter Stephenson
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Stephenson @ 2004-03-24 12:29 UTC (permalink / raw)
  To: Nelson H. F. Beebe, Zsh hackers list

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@csr.com>                  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
**********************************************************************


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-03-24 12:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-23 17:54 zsh-4.1.1 and trap '...' DEBUG: a bug or a feature? Nelson H. F. Beebe
2004-03-23 18:20 ` Wayne Davison
2004-03-23 18:49 ` Peter Stephenson
2004-03-24 12:29   ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).