diff options
author | cracauer <cracauer@FreeBSD.org> | 1998-09-08 13:16:52 +0000 |
---|---|---|
committer | cracauer <cracauer@FreeBSD.org> | 1998-09-08 13:16:52 +0000 |
commit | b1a46a64f829789406b9192367e98c3e10a73a4e (patch) | |
tree | f51c694206a7892088fd5524f3f67bfcfe6d6fb0 /bin | |
parent | 2fb5d649f8cd92ceccd7e5cc137dbee19c2ed487 (diff) | |
download | FreeBSD-src-b1a46a64f829789406b9192367e98c3e10a73a4e.zip FreeBSD-src-b1a46a64f829789406b9192367e98c3e10a73a4e.tar.gz |
If traps are set, they are now executed even when a signal-blocking
foreground child is running. Formerly, traps were exceuted after the
next child exit.
The enables the user to put a breaking wrapper around a blocking
application:
(trap 'echo trap ; exit 1' 2; ./pestyblocker; echo -n)
The "echo -n" after the child call is needed to prevent sh from
optimizing the trap-executing shell away. I'm working on this.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/jobs.c | 11 | ||||
-rw-r--r-- | bin/sh/jobs.h | 3 | ||||
-rw-r--r-- | bin/sh/trap.c | 23 |
3 files changed, 27 insertions, 10 deletions
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 202fa67..c08758e 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; #endif static const char rcsid[] = - "$Id: jobs.c,v 1.21 1998/08/24 10:20:36 cracauer Exp $"; + "$Id: jobs.c,v 1.22 1998/08/25 09:33:34 cracauer Exp $"; #endif /* not lint */ #include <fcntl.h> @@ -88,6 +88,7 @@ int initialpgrp; /* pgrp of shell on invocation */ int curjob; /* current job */ #endif int in_waitcmd = 0; /* are we in waitcmd()? */ +int in_dowait = 0; /* are we in dowait()? */ volatile sig_atomic_t breakwaitcmd = 0; /* should wait be terminated? */ #if JOBS @@ -712,9 +713,9 @@ waitforjob(jp) INTOFF; TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); - while (jp->state == 0) { - dowait(1, jp); - } + while (jp->state == 0) + if (dowait(1, jp) == -1) + dotrap(); #if JOBS if (jp->jobctl) { #ifdef OLD_TTY_DRIVER @@ -771,11 +772,13 @@ dowait(block, job) int core; int sig; + in_dowait++; TRACE(("dowait(%d) called\n", block)); do { pid = waitproc(block, &status); TRACE(("wait returns %d, status=%d\n", pid, status)); } while (pid == -1 && errno == EINTR && breakwaitcmd == 0); + in_dowait--; if (breakwaitcmd != 0) { breakwaitcmd = 0; return -1; diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h index b164b2f2..7b1d431 100644 --- a/bin/sh/jobs.h +++ b/bin/sh/jobs.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)jobs.h 8.2 (Berkeley) 5/4/95 - * $Id: jobs.h,v 1.7 1998/08/24 10:20:36 cracauer Exp $ + * $Id: jobs.h,v 1.8 1998/08/25 09:33:34 cracauer Exp $ */ /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ @@ -79,6 +79,7 @@ struct job { extern pid_t backgndpid; /* pid of last background process */ extern int job_warning; /* user was warned about stopped jobs */ extern int in_waitcmd; /* are we in waitcmd()? */ +extern int in_dowait; /* are we in dowait()? */ extern volatile sig_atomic_t breakwaitcmd; /* should wait be terminated? */ void setjobctl __P((int)); diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 0d8558b..9cb3d0b 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; #endif static const char rcsid[] = - "$Id: trap.c,v 1.13 1998/08/25 08:49:47 cracauer Exp $"; + "$Id: trap.c,v 1.14 1998/08/25 09:33:34 cracauer Exp $"; #endif /* not lint */ #include <signal.h> @@ -77,7 +77,7 @@ static const char rcsid[] = MKINIT char sigmode[NSIG]; /* current value of signal */ int pendingsigs; /* indicates some signal received */ int in_dotrap; /* do we execute in a trap handler? */ -static char *trap[NSIG]; /* trap handler commands */ +static char *volatile trap[NSIG]; /* trap handler commands */ static volatile sig_atomic_t gotsig[NSIG]; /* indicates specified signal received */ static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ @@ -190,7 +190,7 @@ trapcmd(argc, argv) void clear_traps() { - char **tp; + char *volatile *tp; for (tp = trap ; tp <= &trap[NSIG - 1] ; tp++) { if (*tp && **tp) { /* trap not NULL or SIG_IGN */ @@ -347,6 +347,7 @@ void onsig(signo) int signo; { + int i; #ifndef BSD signal(signo, onsig); @@ -355,12 +356,24 @@ onsig(signo) onint(); return; } + if (signo != SIGCHLD || !ignore_sigchld) gotsig[signo] = 1; pendingsigs++; - if (signo == SIGINT && in_waitcmd != 0) { - dotrap(); + + /* If we are currently in a wait builtin, prepare to break it */ + if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) breakwaitcmd = 1; + /* + * If a trap is set, we need to make sure it is executed even + * when a childs blocks all signals. + */ + for (i = 0; i < NSIG; i++) { + if (signo == i && trap[i] != NULL && + ! (trap[i][0] == ':' && trap[i][1] == '\0')) { + breakwaitcmd = 1; + break; + } } } |