diff options
Diffstat (limited to 'sh.proc.c')
| -rw-r--r-- | sh.proc.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/sh.proc.c b/sh.proc.c index f2356d1b98e9..0af5e03ab68e 100644 --- a/sh.proc.c +++ b/sh.proc.c @@ -1,4 +1,4 @@ -/* $Header: /p/tcsh/cvsroot/tcsh/sh.proc.c,v 3.121 2012/01/25 15:34:41 christos Exp $ */ +/* $Header: /p/tcsh/cvsroot/tcsh/sh.proc.c,v 3.134 2016/09/23 19:17:28 christos Exp $ */ /* * sh.proc.c: Job manipulations */ @@ -32,7 +32,7 @@ */ #include "sh.h" -RCSID("$tcsh: sh.proc.c,v 3.121 2012/01/25 15:34:41 christos Exp $") +RCSID("$tcsh: sh.proc.c,v 3.134 2016/09/23 19:17:28 christos Exp $") #include "ed.h" #include "tc.h" @@ -47,11 +47,9 @@ RCSID("$tcsh: sh.proc.c,v 3.121 2012/01/25 15:34:41 christos Exp $") # define HZ 16 #endif /* aiws */ -#if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) -# if !defined(__ANDROID__) -# define BSDWAIT -# endif -#endif /* _BSD || (IRIS4D && __STDC__) || __lucid || glibc */ +#if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) +# define BSDWAIT +#endif /* _BSD || (IRIS4D && __STDC__) || __lucid */ #ifndef WTERMSIG # define WTERMSIG(w) (((union wait *) &(w))->w_termsig) # ifndef BSDWAIT @@ -191,8 +189,13 @@ loop: # else /* both a wait3 and rusage */ # if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (defined(IRIS4D) && SYSVREL <= 3) || defined(__lucid) || defined(__osf__) +#ifdef __ANDROID__ /* no wait3, only wait4 */ + pid = wait4(-1, &w, + (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); +#else pid = wait3(&w, (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); +#endif /* __ANDROID__ */ # else /* BSDWAIT */ pid = wait3(&w.w_status, (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); @@ -507,6 +510,7 @@ pjwait(struct process *pp) cleanup_push(&oset, sigprocmask_cleanup); pause_mask = oset; sigdelset(&pause_mask, SIGCHLD); + sigaddset(&pause_mask, SIGINT); for (;;) { (void)handle_pending_signals(); jobflags = 0; @@ -593,22 +597,44 @@ void dowait(Char **v, struct command *c) { struct process *pp; + + /* the current block mask to be able to restore */ + sigset_t old_mask; + + /* block mask for critical section: OLD_MASK U {SIGCHLD} */ + sigset_t block_mask; + + /* ignore those during blocking sigsuspend: + OLD_MASK / {SIGCHLD, possibly(SIGINT)} */ sigset_t pause_mask; + int opintr_disabled, gotsig; USE(c); USE(v); pjobs++; + sigprocmask(SIG_BLOCK, NULL, &pause_mask); sigdelset(&pause_mask, SIGCHLD); if (setintr) sigdelset(&pause_mask, SIGINT); + + /* critical section, block also SIGCHLD */ + sigprocmask(SIG_BLOCK, NULL, &block_mask); + sigaddset(&block_mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &block_mask, &old_mask); + + /* detect older SIGCHLDs and remove PRUNNING flag from proclist */ + (void)handle_pending_signals(); + loop: for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_procid && /* pp->p_procid == pp->p_jobid && */ pp->p_flags & PRUNNING) { - (void)handle_pending_signals(); + /* wait for (or pick up alredy blocked) SIGCHLD */ sigsuspend(&pause_mask); + + /* make the 'wait' interuptable by CTRL-C */ opintr_disabled = pintr_disabled; pintr_disabled = 0; gotsig = handle_pending_signals(); @@ -618,6 +644,8 @@ loop: goto loop; } pjobs = 0; + + sigprocmask(SIG_SETMASK, &old_mask, NULL); } /* @@ -963,6 +991,7 @@ pprint(struct process *pp, int flag) struct process *tp; int jobflags, pstatus, pcond; const char *format; + int ohaderr; #ifdef BACKPIPE struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL; @@ -978,6 +1007,9 @@ pprint(struct process *pp, int flag) tp = pp; status = reason = -1; jobflags = 0; + ohaderr = haderr; + /* Print status to stderr, except for jobs built-in */ + haderr = !(flag & JOBLIST); do { #ifdef BACKPIPE /* @@ -1186,6 +1218,7 @@ prcomd: xprintf(" "); ptprint(tp); } + haderr = ohaderr; return (jobflags); } @@ -1284,7 +1317,7 @@ void dojobs(Char **v, struct command *c) { struct process *pp; - int flag = NUMBER | NAME | REASON; + int flag = NUMBER | NAME | REASON | JOBLIST; int i; USE(c); @@ -1833,12 +1866,12 @@ pfork(struct command *t, int wanttty) (void) signal(SIGHUP, SIG_IGN); if (t->t_dflg & F_NICE) { int nval = SIGN_EXTEND_CHAR(t->t_nice); -#ifdef HAVE_SETPRIORITY +#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno) stderror(ERR_SYSTEM, "setpriority", strerror(errno)); -#else /* !HAVE_SETPRIORITY */ +#else /* !HAVE_SETPRIORITY || !PRIO_PROCESS */ (void) nice(nval); -#endif /* !HAVE_SETPRIORITY */ +#endif /* HAVE_SETPRIORITY && PRIO_PROCESS */ } #ifdef F_VER if (t->t_dflg & F_VER) { |
