NetBSD Problem Report #6764

Received: (qmail 26913 invoked from network); 8 Jan 1999 02:27:45 -0000
Message-Id: <199901080225.VAA14271@bill-the-cat.mit.edu>
Date: Thu, 7 Jan 1999 21:25:09 -0500 (EST)
From: "Charles M. Hannum" <root@ihack.net>
Reply-To: mycroft@netbsd.org
To: gnats-bugs@gnats.netbsd.org
Subject: `trap 0' does not work in ksh subshells
X-Send-Pr-Version: 3.95

>Number:         6764
>Category:       bin
>Synopsis:       `trap 0' does not work in ksh subshells
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jan 07 18:35:01 +0000 1999
>Closed-Date:    Sun Oct 06 11:09:55 +0000 2013
>Last-Modified:  Sun Oct 06 11:09:55 +0000 2013
>Originator:     Charles M. Hannum
>Release:        1.3I and earlier
>Organization:
	dis
>Environment:
System: NetBSD zygorthian-space-raiders.mit.edu 1.3H NetBSD 1.3H (ZYGORTHIAN-SPACE-RAIDERS) #5: Sun Nov 8 20:58:49 EST 1998 mycroft@zygorthian-space-raiders.mit.edu:/u2/src/sys/arch/i386/compile/ZYGORTHIAN-SPACE-RAIDERS i386


>Description:

	`trap foo 0' is supposed to execute `foo' when the shell
	exits.  This works correctly with subshells in /bin/sh but not
	in /bin/ksh.  This is a serious compatibility problem with the
	original Korn shell.

>How-To-Repeat:

	The following script should output `win'.  It doesn't.

	#!/bin/ksh
	(trap 'echo win' 0)

>Fix:

	Not analyzed.

>Release-Note:
>Audit-Trail:

From: Kevin Schoedel <kevin@quipu.waterloo-rdp.on.ca>
To: gnats-bugs@gnats.netbsd.org
Cc: pdksh@cs.mun.ca, "Charles M. Hannum" <root@ihack.net>
Subject: Re: bin/6764: `trap 0' does not work in ksh subshells
Date: Sun, 10 Jan 1999 21:53:40 -0500

 In <199901080225.VAA14271@bill-the-cat.mit.edu>, "Charles M. Hannum" <root@ihack.net> wrote:

 >>Description:
 >
 >	`trap foo 0' is supposed to execute `foo' when the shell
 >	exits.  This works correctly with subshells in /bin/sh but not
 >	in /bin/ksh.  This is a serious compatibility problem with the
 >	original Korn shell.
 >
 >>How-To-Repeat:
 >
 >	The following script should output `win'.  It doesn't.
 >
 >	#!/bin/ksh
 >	(trap 'echo win' 0)

 I had a look at this, since I use ksh, and noticed the following do work:

 	(trap 'echo win' 0; exit)
 	(trap 'echo win' 0; return)

 Following on that, the patch below is a possible fix. There is the comment about EXIT vs ERR, which I don't necessarily understand the implications of, so this fix might not be entirely correct, but it does appear to solve the original problem.

 This problem still appears in pdksh 5.2.13, so I am cc'ing <pdksh@cs.mun.ca>.
 The complete original problem report can be found via http://www.NetBSD.org/cgi-bin/query-pr-single.pl?number=6764


 *** main.c.orig	Sun Jan 10 13:23:38 1999
 --- main.c	Sun Jan 10 13:23:25 1999
 ***************
 *** 626,632 ****
   	int i;
   {
   	/* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */
 ! 	if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR)
   			   && sigtraps[SIGEXIT_].trap))
   	{
   		runtrap(&sigtraps[SIGEXIT_]);
 --- 626,633 ----
   	int i;
   {
   	/* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */
 ! 	if ((i == LEXIT || i == LLEAVE)
 ! 	|| (Flag(FERREXIT) && (i == LERROR || i == LINTR)
   			   && sigtraps[SIGEXIT_].trap))
   	{
   		runtrap(&sigtraps[SIGEXIT_]);

From: Michael Rendell <michael@cs.mun.ca>
To: Kevin Schoedel <kevin@quipu.waterloo-rdp.on.ca>
Cc: "Charles M. Hannum" <root@ihack.net>, pdksh@cs.mun.ca,
        gnats-bugs@gnats.netbsd.org, jr@cs.mun.ca
Subject: Re: bin/6764: `trap 0' does not work in ksh subshells
Date: Mon, 11 Jan 1999 17:11:24 -0330 (NST)

 Hi,

 On 11-Jan-99 Kevin Schoedel wrote:
  >In <199901080225.VAA14271@bill-the-cat.mit.edu>, "Charles M. Hannum"
  ><root@ihack.net> wrote:
  >>>Description:
  >>
  >>     `trap foo 0' is supposed to execute `foo' when the shell
  >>     exits.  This works correctly with subshells in /bin/sh but not
  >>     in /bin/ksh.  This is a serious compatibility problem with the
  >>     original Korn shell.
  >>
 ...
  >I had a look at this, since I use ksh, and noticed the following do work:
  >
  >      (trap 'echo win' 0; exit)
  >      (trap 'echo win' 0; return)
  >
  >Following on that, the patch below is a possible fix. There is the comment
  >about EXIT vs ERR, which I don't necessarily understand the implications of,
  >so this fix might not be entirely correct, but it does appear to solve the
  >original problem.
  ...
  >*** main.c.orig       Sun Jan 10 13:23:38 1999
  >--- main.c    Sun Jan 10 13:23:25 1999
  >***************
  >*** 626,632 ****
  >      int i;
  >  {
  >      /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */
  >!     if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR)
  >                         && sigtraps[SIGEXIT_].trap))
  >      {
  >              runtrap(&sigtraps[SIGEXIT_]);
  >--- 626,633 ----
  >      int i;
  >  {
  >      /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */
  >!     if ((i == LEXIT || i == LLEAVE)
  >!     || (Flag(FERREXIT) && (i == LERROR || i == LINTR)
  >                         && sigtraps[SIGEXIT_].trap))
  >      {
  >              runtrap(&sigtraps[SIGEXIT_]);

 LLEAVE is used internally to mean `leave and don't (redo) exit traps, et al',
 so this isn't a good thing to do.

 Here is another fix which may work (I've done a bit of testing, but not
 alot).  The main thing is to do an unwind(LEXIT) when subshells exit
 (used to just call exit).  Some care is needed to ensure traps are only
 executed in the indended process.

 [These diffs will be in the next unstable release]

 *** pdksh-unstable-5.2.13.6/exec.c      Fri Dec 18 14:08:08 1998
 --- exec.c      Mon Jan 11 16:49:34 1999
 ***************
 *** 433,439 ****

         quitenv();              /* restores IO */
         if ((flags&XEXEC))
 !               exit(rv);       /* exit child */
         if (rv != 0 && !(flags & XERROK)) {
                 if (Flag(FERREXIT))
                         unwind(LERROR);
 --- 433,439 ----

         quitenv();              /* restores IO */
         if ((flags&XEXEC))
 !               unwind(LEXIT);  /* exit child */
         if (rv != 0 && !(flags & XERROK)) {
                 if (Flag(FERREXIT))
                         unwind(LERROR);
 *** pdksh-unstable-5.2.13.6/sh.h        Wed Dec 16 15:19:45 1998
 --- sh.h        Mon Jan 11 16:55:06 1999
 ***************
 *** 539,544 ****
 --- 539,545 ----
         char   *trap;           /* trap command */
         int     volatile set;   /* trap pending */
         int     flags;          /* TF_* */
 +       int     setters_pid;    /* pid of process that set trap */
         handler_t cursig;       /* current handler (valid if TF_ORIG_* set) */
         handler_t shtrap;       /* shell signal handler */
   } Trap;
 *** pdksh-unstable-5.2.13.6/trap.c      Mon Dec 14 17:09:13 1998
 --- trap.c      Mon Jan 11 16:54:28 1999
 ***************
 *** 233,243 ****
 --- 233,249 ----
         if (trapstr[0] == '\0') /* SIG_IGN */
                 return;
         if (i == SIGEXIT_ || i == SIGERR_) {    /* avoid recursion on these */
 +               /* Only execute trap in process that requested the trap. */
 +               if (procpid != p->setters_pid)
 +                       return;
                 old_changed = p->flags & TF_CHANGED;
                 p->flags &= ~TF_CHANGED;
                 p->trap = (char *) 0;
         }
         oexstat = exstat;
 +       /* Note: trapstr is fully parsed before anything is executed, thus
 +        * no problem with afree(p->trap) in settrap() while still in use.
 +        */
         command(trapstr);
         exstat = oexstat;
         if (i == SIGEXIT_ || i == SIGERR_) {
 ***************
 *** 293,298 ****
 --- 299,305 ----
         p->flags |= TF_CHANGED;
         f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN;

 +       p->setters_pid = procpid;        /* recorded for EXIT and ERR */
         p->flags |= TF_USER_SET;
         if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL)
                 f = trapsig;

 Mike
State-Changed-From-To: open->feedback 
State-Changed-By: christos 
State-Changed-When: Sun Apr 20 18:43:24 EDT 2003 
State-Changed-Why:  
another way to fix this is not to set trap = 0; in cleartraps() 
State-Changed-From-To: feedback->open 
State-Changed-By: tls 
State-Changed-When: Wed Mar 31 04:54:07 UTC 2004 
State-Changed-Why:  
If we know two ways to fix this, but just aren't committing them, this bug 
should not be in "feedback" state for years on end. 
From: "Julio Merino" <jmmv@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/6764 CVS commit: src/tests/util/sh
Date: Fri, 29 Apr 2011 12:49:36 +0000

 Module Name:	src
 Committed By:	jmmv
 Date:		Fri Apr 29 12:49:36 UTC 2011

 Modified Files:
 	src/tests/util/sh: t_exit.sh

 Log Message:
 Add test cases for PR bin/6764: 'trap ... 0' is supposed to execute the
 command when the shell exits but it does not work in ksh when the shells
 exits "implicitly" (without an explicit exit/return statement).

 These new tests cover both sh and ksh.  The ksh part of this does not
 strictly belong to this directory, but I think it'd be nice to extend
 all the tests in here to cover both interpreters whenever that makes
 sense, much like we do with the file system tests.


 To generate a diff of this commit:
 cvs rdiff -u -r1.1 -r1.2 src/tests/util/sh/t_exit.sh

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/6764 CVS commit: src/bin/ksh
Date: Sun, 25 Mar 2012 13:23:49 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Sun Mar 25 17:23:49 UTC 2012

 Modified Files:
 	src/bin/ksh: exec.c

 Log Message:
 PR/6764: Charles M. Hannum: `trap 0' does not work in ksh subshells. When
 subshells exit normally, use unwind(LEXIT) instead of unwind(LLEAVE) so that
 traps get executed.


 To generate a diff of this commit:
 cvs rdiff -u -r1.14 -r1.15 src/bin/ksh/exec.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->feedback
State-Changed-By: wiz@NetBSD.org
State-Changed-When: Sun, 25 Mar 2012 17:44:10 +0000
State-Changed-Why:
Does christos fix solve the problem for you?


State-Changed-From-To: feedback->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sun, 06 Oct 2013 11:09:55 +0000
State-Changed-Why:
18-month feedback timeout


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.