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