diff options
author | cracauer <cracauer@FreeBSD.org> | 1998-02-06 18:14:26 +0000 |
---|---|---|
committer | cracauer <cracauer@FreeBSD.org> | 1998-02-06 18:14:26 +0000 |
commit | 69ec138f358c3e71925110f6c3885d7e2d26bdb7 (patch) | |
tree | ea2a7072ce0481640823b2c72b1c2ee439a00cf2 | |
parent | d5b09c81eced1f16f3f4629fb7fbafca071830c8 (diff) | |
download | FreeBSD-src-69ec138f358c3e71925110f6c3885d7e2d26bdb7.zip FreeBSD-src-69ec138f358c3e71925110f6c3885d7e2d26bdb7.tar.gz |
Fix handling of SIGINT/SIGQUIT for foreground subprocesses. Most
urgent need is when you run sh around a program that intentionally
uses SIGQUIT/SIGINT for asynchronous events, i.e. $EDITOR started from
system(2), like many mailers do. This fixes PR bin/1206 and possibly
bin/4241.
The solution committed has been tested for a large number of possible
cases (see recent discussion on cvs-committers). I completed a make
world, made sure 'make world' is interruptable and used the changed
/bin/sh as a login shell all day, including job control and using
SIGQUIT-catching programs (to write this message :-).
PR: bin/1206
Reviewed by: discussion on cvs-commiters
-rw-r--r-- | bin/sh/jobs.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index a17b5d0..a75fae0 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: jobs.c,v 1.16 1997/08/18 02:53:19 steve Exp $ + * $Id: jobs.c,v 1.17 1997/12/10 22:18:53 eivind Exp $ */ #ifndef lint @@ -85,6 +85,9 @@ MKINIT pid_t backgndpid = -1; /* pid of last background process */ int initialpgrp; /* pgrp of shell on invocation */ int curjob; /* current job */ #endif +sig_t oldsigint; +sig_t oldsigquit; +int oldsigs_valid = 0; #if JOBS STATIC void restartjob __P((struct job *)); @@ -574,6 +577,11 @@ forkshell(jp, n, mode) TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, mode)); INTOFF; + if (mode == FORK_FG) { + oldsigquit = signal(SIGQUIT,SIG_IGN); + oldsigint = signal(SIGINT,SIG_IGN); + oldsigs_valid = 1; + } pid = fork(); if (pid == -1) { TRACE(("Fork failed, errno=%d\n", errno)); @@ -586,6 +594,8 @@ forkshell(jp, n, mode) int i; TRACE(("Child shell %d\n", getpid())); + signal(SIGQUIT,SIG_DFL); + signal(SIGINT,SIG_DFL); wasroot = rootshell; rootshell = 0; for (i = njobs, p = jobtab ; --i >= 0 ; p++) @@ -700,6 +710,12 @@ waitforjob(jp) while (jp->state == 0) { dowait(1, jp); } + if (oldsigs_valid) { + signal(SIGQUIT,oldsigquit); + signal(SIGINT,oldsigint); + oldsigs_valid = 0; + } + #if JOBS if (jp->jobctl) { #ifdef OLD_TTY_DRIVER |