Date: Wed, 6 May 1998 11:57:00 +0200 From: Martin Cracauer <cracauer@cons.org> To: Bruce Evans <bde@zeta.org.au>, cracauer@cons.org, freebsd-current@FreeBSD.ORG Subject: Re: make/SIGINT (Re: cvs commit: src/bin/sh jobs.c) Message-ID: <19980506115700.32044@cons.org> In-Reply-To: <19980505122917.01946@cons.org>; from Martin Cracauer on Tue, May 05, 1998 at 12:29:17PM %2B0200 References: <199804191143.VAA00099@godzilla.zeta.org.au> <19980422101203.65361@cons.org> <19980505122917.01946@cons.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii > The only test this sh version still fails on is that the wait builtin > isn't interruptable by SIGINT. The appended version makes the wait builtin interruptable, on the cost of two new global variables. Martin -- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Martin Cracauer <cracauer@cons.org> http://www.cons.org/cracauer cracauer@wavehh.hanse.de (batched, preferred for large mails) Tel.: (private) +4940 5221829 Fax.: (private) +4940 5228536 Paper: (private) Waldstrasse 200, 22846 Norderstedt, Germany --LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=diff ? l ? builtins.c ? builtins.h ? mknodes ? nodes.h ? nodes.c ? mksyntax ? syntax.c ? syntax.h ? token.h ? sh ? y.tab.h ? arith.c ? arith_lex.c ? mkinit ? init.c ? sh.1.gz ? README ? .depend Index: error.c =================================================================== RCS file: /home/ftp/pub/FreeBSD/CVS-FreeBSD/src/bin/sh/error.c,v retrieving revision 1.5.2.1 diff -c -r1.5.2.1 error.c *** error.c 1997/08/25 09:09:38 1.5.2.1 --- error.c 1998/05/06 09:49:40 *************** *** 50,55 **** --- 50,56 ---- #include "output.h" #include "error.h" #include "show.h" + #include "trap.h" #include <signal.h> #include <unistd.h> #include <errno.h> *************** *** 89,116 **** * Called from trap.c when a SIGINT is received. (If the user specifies * that SIGINT is to be trapped or ignored using the trap builtin, then * this routine is not called.) Suppressint is nonzero when interrupts ! * are held using the INTOFF macro. The call to _exit is necessary because ! * there is a short period after a fork before the signal handlers are ! * set to the appropriate value for the child. (The test for iflag is ! * just defensive programming.) */ void onint() { sigset_t sigset; ! if (suppressint) { intpending++; return; } intpending = 0; sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); ! out2str("\n"); ! if (rootshell && iflag) exraise(EXINT); ! else ! _exit(128 + SIGINT); } --- 90,124 ---- * Called from trap.c when a SIGINT is received. (If the user specifies * that SIGINT is to be trapped or ignored using the trap builtin, then * this routine is not called.) Suppressint is nonzero when interrupts ! * are held using the INTOFF macro. If SIGINTs are not suppressed and ! * the shell is not a root shell, then we want to be terminated if we ! * get here, as if we were terminated directly by a SIGINT. Arrange for ! * this here. */ void onint() { sigset_t sigset; ! /* The !in_dotrap is save. The only way we can arrive here with ! * in_dotrap set is that a trap handler set SIGINT to default ! * and killed itself. ! */ ! ! if (suppressint && !in_dotrap) { intpending++; return; } intpending = 0; sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); ! write(STDERR_FILENO, "\n", 1); ! if (rootshell /* && iflag ?? */) exraise(EXINT); ! else { ! signal(SIGINT, SIG_DFL); ! kill(getpid(), SIGINT); ! } } Index: jobs.c =================================================================== RCS file: /home/ftp/pub/FreeBSD/CVS-FreeBSD/src/bin/sh/jobs.c,v retrieving revision 1.8.2.4 diff -c -r1.8.2.4 jobs.c *** jobs.c 1998/02/15 11:32:25 1.8.2.4 --- jobs.c 1998/05/06 09:49:40 *************** *** 85,90 **** --- 85,92 ---- int initialpgrp; /* pgrp of shell on invocation */ int curjob; /* current job */ #endif + int in_waitcmd = 0; /* Are we in waitcmd? */ + volatile sig_atomic_t breakwaitcmd = 0; /* Should wait be terminated? */ #if JOBS STATIC void restartjob __P((struct job *)); *************** *** 383,389 **** } else { job = NULL; } ! for (;;) { /* loop until process terminated or stopped */ if (job != NULL) { if (job->state) { status = job->ps[job->nprocs - 1].status; --- 385,394 ---- } else { job = NULL; } ! in_waitcmd++; ! do { /* loop until process terminated or stopped or SIGINT is ! * received ! */ if (job != NULL) { if (job->state) { status = job->ps[job->nprocs - 1].status; *************** *** 408,415 **** break; } } ! dowait(1, (struct job *)NULL); ! } } --- 413,420 ---- break; } } ! } while (dowait(1, (struct job *)NULL) != -1); ! in_waitcmd--; } *************** *** 725,733 **** st = WTERMSIG(status) + 128; if (! JOBS || jp->state == JOBDONE) freejob(jp); ! CLEAR_PENDING_INT; ! if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) ! kill(getpid(), SIGINT); INTON; return st; } --- 730,741 ---- st = WTERMSIG(status) + 128; if (! JOBS || jp->state == JOBDONE) freejob(jp); ! if (int_pending()) { ! if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) ! kill(getpid(), SIGINT); ! else ! CLEAR_PENDING_INT; ! } INTON; return st; } *************** *** 757,763 **** do { pid = waitproc(block, &status); TRACE(("wait returns %d, status=%d\n", pid, status)); ! } while (pid == -1 && errno == EINTR); if (pid <= 0) return pid; INTOFF; --- 765,775 ---- do { pid = waitproc(block, &status); TRACE(("wait returns %d, status=%d\n", pid, status)); ! } while (pid == -1 && errno == EINTR && breakwaitcmd == 0); ! if (breakwaitcmd != 0) { ! breakwaitcmd = 0; ! return -1; ! } if (pid <= 0) return pid; INTOFF; Index: jobs.h =================================================================== RCS file: /home/ftp/pub/FreeBSD/CVS-FreeBSD/src/bin/sh/jobs.h,v retrieving revision 1.3.2.1 diff -c -r1.3.2.1 jobs.h *** jobs.h 1997/08/25 09:10:02 1.3.2.1 --- jobs.h 1998/05/06 09:49:40 *************** *** 42,47 **** --- 42,48 ---- #define FORK_BG 1 #define FORK_NOJOB 2 + #include <signal.h> /* For sig_atomic_t */ /* * A job structure contains information about a job. A job is either a *************** *** 77,82 **** --- 78,85 ---- 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 wait? */ + extern volatile sig_atomic_t breakwaitcmd; /* Should wait be terminated? */ void setjobctl __P((int)); int fgcmd __P((int, char **)); Index: trap.c =================================================================== RCS file: /home/ftp/pub/FreeBSD/CVS-FreeBSD/src/bin/sh/trap.c,v retrieving revision 1.4.2.2 diff -c -r1.4.2.2 trap.c *** trap.c 1998/02/15 11:32:27 1.4.2.2 --- trap.c 1998/05/06 09:49:40 *************** *** 73,79 **** MKINIT char sigmode[NSIG]; /* current value of signal */ ! int pendingsigs; /* indicates some signal received */ static char *trap[NSIG]; /* trap handler commands */ static char gotsig[NSIG]; /* indicates specified signal received */ static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ --- 73,80 ---- MKINIT char sigmode[NSIG]; /* current value of signal */ ! int pendingsigs; /* indicates some signal received */ ! int in_dotrap = 0; /* Do we execute in a trap handler? */ static char *trap[NSIG]; /* trap handler commands */ static char gotsig[NSIG]; /* indicates specified signal received */ static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ *************** *** 219,229 **** action = S_CATCH; else action = S_IGN; ! if (rootshell && action == S_DFL) { switch (signo) { case SIGINT: ! if (iflag) ! action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG --- 220,229 ---- action = S_CATCH; else action = S_IGN; ! if (action == S_DFL) { switch (signo) { case SIGINT: ! action = S_CATCH; break; case SIGQUIT: #ifdef DEBUG *************** *** 234,248 **** break; } #endif ! /* FALLTHROUGH */ case SIGTERM: ! if (iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: ! if (mflag) action = S_IGN; break; #endif --- 234,249 ---- break; } #endif ! action = S_IGN; ! break; case SIGTERM: ! if (rootshell && iflag) action = S_IGN; break; #if JOBS case SIGTSTP: case SIGTTOU: ! if (rootshell && mflag) action = S_IGN; break; #endif *************** *** 354,359 **** --- 355,364 ---- if (signo != SIGCHLD || !ignore_sigchld) gotsig[signo] = 1; pendingsigs++; + if (signo == SIGINT && in_waitcmd != 0) { + dotrap(); + breakwaitcmd = 1; + } } *************** *** 367,372 **** --- 372,378 ---- int i; int savestatus; + in_dotrap++; for (;;) { for (i = 1; i < NSIG; i++) { if (gotsig[i]) { *************** *** 390,395 **** --- 396,402 ---- if (i >= NSIG) break; } + in_dotrap--; pendingsigs = 0; } *************** *** 401,407 **** setinteractive(on) int on; { ! static int is_interactive = 0; if (on == is_interactive) return; --- 408,414 ---- setinteractive(on) int on; { ! static int is_interactive = -1; if (on == is_interactive) return; Index: trap.h =================================================================== RCS file: /home/ftp/pub/FreeBSD/CVS-FreeBSD/src/bin/sh/trap.h,v retrieving revision 1.3.2.2 diff -c -r1.3.2.2 trap.h *** trap.h 1998/02/15 11:32:27 1.3.2.2 --- trap.h 1998/05/06 09:49:40 *************** *** 38,43 **** --- 38,44 ---- */ extern int pendingsigs; + extern int in_dotrap; int trapcmd __P((int, char **)); void clear_traps __P((void)); --LZvS9be/3tNcYl/X-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19980506115700.32044>