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 --- ChangeLog | 13 ++++++++++++- Src/exec.c | 2 ++ Src/init.c | 1 + Src/jobs.c | 20 ++++++++++++++++++++ Src/signals.c | 10 ++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 834f339db..103dbccf3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-12-02 Peter Stephenson + + * 27442 plus tweak: Src/exec.c, Src/init.c, Src/jobs.c, + Src/signals.c: return status for last background job from + wait even if it's already exited, but only if POSIX_JOBS + is set. + 2009-12-01 Peter Stephenson * Alexey: 27445: Completion/Unix/Command/_ruby: argument can be @@ -5,6 +12,10 @@ 2009-11-30 Peter Stephenson + * 27442: Src/exec.c, Src/init.c, Src/job.s,c Src/signals.c: + add lastpid_status to record status of last background job + even after it's exited. + * 27441: Doc/Zsh/mod_complist.yo, Src/Zle/complist.c: add "sa" highlight code for suffix aliases. @@ -12409,5 +12420,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4827 $ +* $Revision: 1.4828 $ ***************************************************** 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