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