Subject: bin/36079: /bin/sh fails to execute EXIT trap handlers for some subshells
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: M. Levinson <levinsm@users.sourceforge.net>
List: netbsd-bugs
Date: 03/24/2007 12:20:00
>Number: 36079
>Category: bin
>Synopsis: /bin/sh fails to execute EXIT trap handlers for some subshells
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Mar 24 12:20:00 +0000 2007
>Originator: M. Levinson
>Release: NetBSD 4.99.16 from 2007-03-23
>Organization:
>Environment:
$NetBSD: eval.c,v 1.88 2006/10/16 00:36:19 christos Exp $
Architecture: i386
Machine: i386
>Description:
If the final command to be run by a subshell is a shell function
or built-in then /bin/sh executes trap handlers for the EXIT
pseudo-signal before that subshell exits (as expected). But if the
final command to be run by the subshell is an external program then
an identical trap handler won't be executed; in this case the
subshell doesn't fork before it execs the program, so of course
after the exec the subshell never gets a chance to call the
exitshell() function from src/bin/sh/trap.c. With the patch below
the subshell will fork in this case, so when the subshell exits it
will call exitshell() and any trap handler will be executed as
expected.
>How-To-Repeat:
This command echoes "exiting" as expected:
sh -c "( trap 'echo exiting' EXIT; /usr/bin/true; : )"
But this command does not:
sh -c "( trap 'echo exiting' EXIT; /usr/bin/true )"
>Fix:
--- src/bin/sh/eval.c 2006-10-19 06:49:12.000000000 -0500
+++ src/bin/sh/eval.c 2007-03-23 13:46:16.000000000 -0400
@@ -814,7 +814,7 @@
/* Fork off a child process if necessary. */
if (cmd->ncmd.backgnd
- || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
+ || cmdentry.cmdtype == CMDNORMAL
|| ((flags & EV_BACKCMD) != 0
&& ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
|| cmdentry.u.bltin == dotcmd