On Sat, Dec 01, 2018 at 04:45:39PM +0800, Herbert Xu wrote:
> 
> Hmm, I think this breaks the following case which used to work:
> 
>       dash -c 'trap "(:; exit) && echo BUG" EXIT; false'
> 
> I know this makes no sense but almost every other shell does it
> this way.

Here is a new patch that fixes the reported issue for both signal
traps and the EXIT trap.

---8<---
We unconditionally restore the saved status in exitreset, which
is incorrect as we only want to do it for exitcmd and returncmd.
This patch fixes the problem by introducing EXEND.

Reported-by: Martijn Dekker <[email protected]>
Fixes: da30b4b78769 ("[BUILTIN] Exit without arguments in a trap...")
Signed-off-by: Herbert Xu <[email protected]>

diff --git a/src/error.h b/src/error.h
index 9630b56..94e30a2 100644
--- a/src/error.h
+++ b/src/error.h
@@ -66,7 +66,8 @@ extern int exception;
 /* exceptions */
 #define EXINT 0                /* SIGINT received */
 #define EXERROR 1      /* a generic error */
-#define EXEXIT 4       /* exit the shell */
+#define EXEND 3                /* exit the shell */
+#define EXEXIT 4       /* exit the shell via exitcmd */
 
 
 /*
diff --git a/src/eval.c b/src/eval.c
index 546ee1b..3cea2a3 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -114,12 +114,13 @@ STATIC const struct builtincmd bltin = {
 INCLUDE "eval.h"
 
 EXITRESET {
-       evalskip = 0;
-       loopnest = 0;
        if (savestatus >= 0) {
-               exitstatus = savestatus;
+               if (exception == EXEXIT || evalskip == SKIPFUNCDEF)
+                       exitstatus = savestatus;
                savestatus = -1;
        }
+       evalskip = 0;
+       loopnest = 0;
 }
 #endif
 
@@ -314,7 +315,7 @@ out:
 
        if (flags & EV_EXIT) {
 exexit:
-               exraise(EXEXIT);
+               exraise(EXEND);
        }
 
        return exitstatus;
diff --git a/src/exec.c b/src/exec.c
index 9d0215a..87354d4 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -143,7 +143,7 @@ shellexec(char **argv, const char *path, int idx)
        exitstatus = exerrno;
        TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
                argv[0], e, suppressint ));
-       exerror(EXEXIT, "%s: %s", argv[0], errmsg(e, E_EXEC));
+       exerror(EXEND, "%s: %s", argv[0], errmsg(e, E_EXEC));
        /* NOTREACHED */
 }
 
diff --git a/src/main.c b/src/main.c
index 6d53e00..6b3a090 100644
--- a/src/main.c
+++ b/src/main.c
@@ -111,7 +111,7 @@ main(int argc, char **argv)
                e = exception;
 
                s = state;
-               if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
+               if (e == EXEND || e == EXEXIT || s == 0 || iflag == 0 || shlvl)
                        exitshell();
 
                reset();
diff --git a/src/trap.c b/src/trap.c
index ab0ecd4..64917fc 100644
--- a/src/trap.c
+++ b/src/trap.c
@@ -397,8 +397,10 @@ exitshell(void)
                trap[0] = NULL;
                evalskip = 0;
                evalstring(p, 0);
+               evalskip = SKIPFUNCDEF;
        }
 out:
+       exitreset();
        /*
         * Disable job control so that whoever had the foreground before we
         * started can get it back.
@@ -406,7 +408,7 @@ out:
        if (likely(!setjmp(loc.loc)))
                setjobctl(0);
        flushall();
-       _exit(savestatus);
+       _exit(exitstatus);
        /* NOTREACHED */
 }
 

-- 
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

Reply via email to