ash: hopefully close bug 4324. With testcase.

function                                             old     new   delta
evaltree                                             621     869    +248
popstring                                            134     140      +6
This commit is contained in:
Denis Vlasenko 2008-07-26 13:45:57 +00:00
parent 2b2e267b43
commit 4e19a9c81a
3 changed files with 57 additions and 17 deletions

View File

@ -203,7 +203,7 @@ struct globals_misc {
#define S_RESET 5 /* temporary - to reset a hard ignored sig */
/* indicates specified signal received */
char gotsig[NSIG - 1];
char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
char *trap[NSIG];
/* Rarely referenced stuff */
@ -7846,12 +7846,12 @@ dotrap(void)
pendingsig = 0;
xbarrier();
for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
for (i = 1, q = gotsig; i < NSIG; i++, q++) {
if (!*q)
continue;
*q = '\0';
p = trap[i + 1];
p = trap[i];
if (!p)
continue;
skip = evalstring(p, SKIPEVAL);
@ -7881,16 +7881,33 @@ static void prehash(union node *);
static void
evaltree(union node *n, int flags)
{
struct jmploc *volatile savehandler = exception_handler;
struct jmploc jmploc;
int checkexit = 0;
void (*evalfn)(union node *, int);
unsigned isor;
int status;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
goto out;
goto out1;
}
TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
getpid(), n, n->type, flags));
exception_handler = &jmploc;
{
int err = setjmp(jmploc.loc);
if (err) {
/* if it was a signal, check for trap handlers */
if (exception == EXSIG)
goto out;
/* continue on the way out */
exception_handler = savehandler;
longjmp(exception_handler->loc, err);
}
}
switch (n->type) {
default:
#if DEBUG
@ -7936,19 +7953,20 @@ evaltree(union node *n, int flags)
goto calleval;
case NAND:
case NOR:
case NSEMI:
case NSEMI: {
#if NAND + 1 != NOR
#error NAND + 1 != NOR
#endif
#if NOR + 1 != NSEMI
#error NOR + 1 != NSEMI
#endif
isor = n->type - NAND;
unsigned is_or = is_or = n->type - NAND;
evaltree(
n->nbinary.ch1,
(flags | ((isor >> 1) - 1)) & EV_TESTED
(flags | ((is_or >> 1) - 1)) & EV_TESTED
);
if (!exitstatus == isor)
if (!exitstatus == is_or)
break;
if (!evalskip) {
n = n->nbinary.ch2;
@ -7959,6 +7977,7 @@ evaltree(union node *n, int flags)
break;
}
break;
}
case NIF:
evaltree(n->nif.test, EV_TESTED);
if (evalskip)
@ -7979,8 +7998,11 @@ evaltree(union node *n, int flags)
exitstatus = status;
break;
}
out:
if ((checkexit & exitstatus))
exception_handler = savehandler;
out1:
if (checkexit & exitstatus)
evalskip |= SKIPEVAL;
else if (pendingsig && dotrap())
goto exexit;
@ -11907,18 +11929,15 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
if (!*ap) {
for (signo = 0; signo < NSIG; signo++) {
if (trap[signo] != NULL) {
const char *sn;
sn = get_signame(signo);
out1fmt("trap -- %s %s\n",
single_quote(trap[signo]), sn);
single_quote(trap[signo]),
get_signame(signo));
}
}
return 0;
}
if (!ap[1])
action = NULL;
else
action = NULL;
if (ap[1])
action = *ap++;
while (*ap) {
signo = get_signum(*ap);

View File

@ -0,0 +1,3 @@
sleeping
child exits as expected
parent exits

View File

@ -0,0 +1,18 @@
#!/bin/sh
$THIS_SH -c '
cleanup() {
echo "child exits as expected"
exit
}
trap cleanup HUP
echo "sleeping"
sleep 1
echo "BAD exit from child!"
' &
child=$!
sleep 0.1 # let child install handler first
kill -HUP $child
wait
echo "parent exits"