On Thu, Feb 24, 2005 at 09:07:50PM +0000, Gerrit Pape wrote:
> 
> A subshell forked in eval or a dot file within an or list does not
> return, causing the parent shell to block:

Good catch.  We need to check whether the EXEVAL is thrown by a subshell
and if so relay it to the top.

Please try these two patches instead.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
===== jobs.c 1.61 vs edited =====
--- 1.61/src/jobs.c     2004-08-07 13:48:42 +10:00
+++ edited/jobs.c       2005-02-25 11:48:15 +11:00
@@ -838,19 +838,19 @@
 STATIC inline void
 forkchild(struct job *jp, union node *n, int mode)
 {
-       int wasroot;
+       int oldlvl;
        pid_t pgrp;
 
        TRACE(("Child shell %d\n", getpid()));
-       wasroot = rootshell;
-       rootshell = 0;
+       oldlvl = shlvl;
+       shlvl++;
 
        closescript();
        clear_traps();
 #if JOBS
        /* do job control only in root shell */
        jobctl = 0;
-       if (mode != FORK_NOJOB && jp->jobctl && wasroot) {
+       if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
                if (jp->nprocs == 0)
                        pgrp = getpid();
                else
@@ -872,7 +872,7 @@
                                error("Can't open %s", _PATH_DEVNULL);
                }
        }
-       if (wasroot && iflag) {
+       if (!oldlvl && iflag) {
                setsignal(SIGINT);
                setsignal(SIGQUIT);
                setsignal(SIGTERM);
===== main.c 1.33 vs edited =====
--- 1.33/src/main.c     2003-10-29 21:22:45 +11:00
+++ edited/main.c       2005-02-25 11:48:52 +11:00
@@ -85,7 +85,7 @@
 #define PROFILE 0
 
 int rootpid;
-int rootshell;
+int shlvl;
 #ifdef __GLIBC__
 int *dash_errno;
 #endif
@@ -174,7 +174,6 @@
        trputs("Shell args:  ");  trargs(argv);
 #endif
        rootpid = getpid();
-       rootshell = 1;
        init();
        setstackmark(&smark);
        procargs(argc, argv);
===== main.h 1.3 vs edited =====
--- 1.3/src/main.h      2003-03-25 22:29:39 +11:00
+++ edited/main.h       2005-02-25 11:45:03 +11:00
@@ -42,8 +42,10 @@
 
 /* pid of main shell */
 extern int rootpid;
-/* true if we aren't a child of the main shell */
-extern int rootshell;
+/* shell level: 0 for the main shell, 1 for its children, and so on */
+extern int shlvl;
+#define rootshell (!shlvl)
+
 #ifdef __GLIBC__
 /* glibc sucks */
 extern int *dash_errno;
===== error.h 1.25 vs edited =====
--- 1.25/src/error.h    2004-06-29 20:55:46 +10:00
+++ edited/error.h      2005-02-25 20:49:22 +11:00
@@ -75,6 +75,7 @@
 #define EXEXEC 3       /* command execution failed */
 #define EXEXIT 4       /* exit the shell */
 #define EXSIG 5                /* trapped signal in wait(1) */
+#define EXEVAL 6       /* exit the shell due to set -e */
 
 
 /*
===== eval.c 1.99 vs edited =====
--- 1.99/src/eval.c     2004-03-07 21:46:03 +11:00
+++ edited/eval.c       2005-02-25 20:51:52 +11:00
@@ -73,6 +73,7 @@
 #include "error.h"
 #include "show.h"
 #include "mystring.h"
+#include "main.h"
 #ifndef SMALL
 #include "myhistedit.h"
 #endif
@@ -322,8 +323,10 @@
 out:
        if (pendingsigs)
                dotrap();
-       if (flags & EV_EXIT || checkexit & exitstatus)
+       if (flags & EV_EXIT)
                exraise(EXEXIT);
+       if (checkexit & exitstatus)
+               exraise(EXEVAL);
 }
 
 
@@ -708,12 +711,14 @@
        int spclbltin;
        int execcmd;
        int status;
+       int oldlvl;
        char **nargv;
 
        /* First expand the arguments. */
        TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
        setstackmark(&smark);
        back_exitstatus = 0;
+       oldlvl = shlvl;
 
        cmdentry.cmdtype = CMDBUILTIN;
        cmdentry.u.cmd = &bltin;
@@ -880,7 +885,8 @@
                                status = j + 128;
                        exitstatus = status;
 
-                       if (i == EXINT || spclbltin > 0) {
+                       if (i == EXINT || (i != EXEVAL && spclbltin > 0) ||
+                           oldlvl != shlvl) {
 raise:
                                longjmp(handler->loc, 1);
                        }
===== main.c 1.34 vs edited =====
--- 1.34/src/main.c     2005-02-25 20:49:12 +11:00
+++ edited/main.c       2005-02-25 21:06:56 +11:00
@@ -138,13 +138,17 @@
                        status = 2;
                        break;
 
+               case EXEXIT:
+               case EXEVAL:
+                       state = 0;
+                       /* fall through */
                default:
                        status = exitstatus;
                        break;
                }
                exitstatus = status;
 
-               if (e == EXEXIT || state == 0 || iflag == 0 || ! rootshell)
+               if (state == 0 || iflag == 0 || shlvl)
                        exitshell();
 
                if (e == EXINT

Reply via email to