From 3206b8a2eac54b75a181859cd98130c5219c3126 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 2 Dec 2009 09:46:12 +0000 Subject: 27442 plus tweak: wait returns status for $! even if exited --- Src/exec.c | 2 ++ Src/init.c | 1 + Src/jobs.c | 20 ++++++++++++++++++++ Src/signals.c | 10 ++++++++++ 4 files changed, 33 insertions(+) (limited to 'Src') diff --git a/Src/exec.c b/Src/exec.c index 2263bd640..172d302da 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2727,6 +2727,8 @@ execcmd(Estate state, int input, int output, int how, int last1) #endif if (how & Z_ASYNC) { lastpid = (zlong) pid; + /* indicate it's possible to set status for lastpid */ + lastpid_status = -2L; } else if (!jobtab[thisjob].stty_in_env && varspc) { /* search for STTY=... */ Wordcode p = varspc; diff --git a/Src/init.c b/Src/init.c index be1055a53..cf5a6074d 100644 --- a/Src/init.c +++ b/Src/init.c @@ -913,6 +913,7 @@ setupvals(void) bufstack = znewlinklist(); hsubl = hsubr = NULL; lastpid = 0; + lastpid_status = -1L; bshin = SHIN ? fdopen(SHIN, "r") : stdin; if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) { #ifdef _IONBF diff --git a/Src/jobs.c b/Src/jobs.c index d0916174f..9b7b053ee 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -104,6 +104,15 @@ int prev_errflag, prev_breaks, errbrk_saved; /**/ int numpipestats, pipestats[MAX_PIPESTATS]; +/* + * The status associated with the process lastpid. + * -1 if not set and no associated lastpid + * -2 if lastpid is set and status isn't yet + * else the value returned by wait(). + */ +/**/ +long lastpid_status; + /* Diff two timevals for elapsed-time computations */ /**/ @@ -1109,6 +1118,14 @@ addproc(pid_t pid, char *text, int aux, struct timeval *bgtime) { Process pn, *pnlist; + if (pid == lastpid && lastpid_status != -2L) { + /* + * The status for the previous lastpid is invalid. + * Presumably process numbers have wrapped. + */ + lastpid_status = -1L; + } + DPUTS(thisjob == -1, "No valid job in addproc."); pn = (Process) zshcalloc(sizeof *pn); pn->pid = pid; @@ -1845,6 +1862,9 @@ bin_fg(char *name, char **argv, Options ops, int func) retval = waitforpid(pid, 1); if (!retval) retval = lastval2; + } else if (isset(POSIXJOBS) && + pid == lastpid && lastpid_status >= 0L) { + retval = (int)lastpid_status; } else { zwarnnam(name, "pid %d is not a child of this shell", pid); /* presumably lastval2 doesn't tell us a heck of a lot? */ diff --git a/Src/signals.c b/Src/signals.c index 4bc1de016..f67a3e8ca 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -530,6 +530,7 @@ zhandler(int sig) * Find the process and job containing this pid and * update it. */ + pn = NULL; if (findproc(pid, &jn, &pn, 0)) { #if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE) struct timezone dummy_tz; @@ -551,6 +552,15 @@ zhandler(int sig) */ get_usage(); } + /* + * Remember the status associated with $!, so we can + * wait for it even if it's exited. This value is + * only used if we can't find the PID in the job table, + * so it doesn't matter that the value we save here isn't + * useful until the process has exited. + */ + if (pn != NULL && pid == lastpid && lastpid_status != -1L) + lastpid_status = lastval2; } break; -- cgit 1.4.1