diff options
author | Peter Stephenson <pws@zsh.org> | 2016-09-15 11:42:28 +0100 |
---|---|---|
committer | Peter Stephenson <pws@zsh.org> | 2016-09-16 09:39:33 +0100 |
commit | 01ae64c0d74c17e36bfe6f52394a59754b8e8c92 (patch) | |
tree | 5c76926c158e8ef5460b86b1c5abc7dbc61a9151 /Src | |
parent | d523ddaba2cd160343b54d3e38ea001c63a87dc6 (diff) | |
download | zsh-01ae64c0d74c17e36bfe6f52394a59754b8e8c92.tar.gz zsh-01ae64c0d74c17e36bfe6f52394a59754b8e8c92.tar.xz zsh-01ae64c0d74c17e36bfe6f52394a59754b8e8c92.zip |
39331: Reparent subjob on fork with exited superjob.
Fixes case of v() { { vim - } always { true } } ls | v ^Z fg Tentative fix: still a race at exit where zsh forked by ^Z is stopped when restarted.
Diffstat (limited to 'Src')
-rw-r--r-- | Src/exec.c | 19 | ||||
-rw-r--r-- | Src/jobs.c | 11 | ||||
-rw-r--r-- | Src/zsh.h | 5 |
3 files changed, 31 insertions, 4 deletions
diff --git a/Src/exec.c b/Src/exec.c index cfd633add..21270c82d 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1570,6 +1570,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) if (nowait) { if(!pline_level) { + int jobsub; struct process *pn, *qn; curjob = newjob; @@ -1582,6 +1583,20 @@ execpline(Estate state, wordcode slcode, int how, int last1) if (!jn->procs->next || lpforked == 2) { jn->gleader = list_pipe_pid; jn->stat |= STAT_SUBLEADER; + /* + * Pick up any subjob that's still lying around + * as it's now our responsibility. + * If we find it we're a SUPERJOB. + */ + for (jobsub = 1; jobsub <= maxjob; jobsub++) { + Job jnsub = jobtab + jobsub; + if (jnsub->stat & STAT_SUBJOB_ORPHANED) { + jn->other = jobsub; + jn->stat |= STAT_SUPERJOB; + jnsub->stat &= ~STAT_SUBJOB_ORPHANED; + jnsub->other = list_pipe_pid; + } + } } for (pn = jobtab[jn->other].procs; pn; pn = pn->next) if (WIFSTOPPED(pn->status)) @@ -1593,7 +1608,8 @@ execpline(Estate state, wordcode slcode, int how, int last1) } jn->stat &= ~(STAT_DONE | STAT_NOPRINT); - jn->stat |= STAT_STOPPED | STAT_CHANGED | STAT_LOCKED; + jn->stat |= STAT_STOPPED | STAT_CHANGED | STAT_LOCKED | + STAT_INUSE; printjob(jn, !!isset(LONGLISTJOBS), 1); } else if (newjob != list_pipe_job) @@ -1669,6 +1685,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) jobtab[list_pipe_job].stat |= STAT_SUPERJOB; jn->stat |= STAT_SUBJOB | STAT_NOPRINT; jn->other = pid; + jn->gleader = jobtab[list_pipe_job].gleader; } if ((list_pipe || last1) && hasprocs(list_pipe_job)) killpg(jobtab[list_pipe_job].gleader, SIGSTOP); diff --git a/Src/jobs.c b/Src/jobs.c index 6bc361609..9284c7124 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -128,7 +128,7 @@ makerunning(Job jn) Process pn; jn->stat &= ~STAT_STOPPED; - for (pn = jn->procs; pn; pn = pn->next) + for (pn = jn->procs; pn; pn = pn->next) { #if 0 if (WIFSTOPPED(pn->status) && (!(jn->stat & STAT_SUPERJOB) || pn->next)) @@ -136,6 +136,7 @@ makerunning(Job jn) #endif if (WIFSTOPPED(pn->status)) pn->status = SP_RUNNING; + } if (jn->stat & STAT_SUPERJOB) makerunning(jobtab + jn->other); @@ -236,7 +237,7 @@ handle_sub(int job, int fg) if ((sj->stat & STAT_DONE) || (!sj->procs && !sj->auxprocs)) { struct process *p; - for (p = sj->procs; p; p = p->next) + for (p = sj->procs; p; p = p->next) { if (WIFSIGNALED(p->status)) { if (jn->gleader != mypgrp && jn->procs->next) killpg(jn->gleader, WTERMSIG(p->status)); @@ -246,6 +247,7 @@ handle_sub(int job, int fg) kill(sj->other, WTERMSIG(p->status)); break; } + } if (!p) { int cp; @@ -1316,6 +1318,11 @@ deletejob(Job jn, int disowning) attachtty(mypgrp); adjustwinsize(0); } + if (jn->stat & STAT_SUPERJOB) { + Job jno = jobtab + jn->other; + if (jno->stat & STAT_SUBJOB) + jno->stat |= STAT_SUBJOB_ORPHANED; + } freejob(jn, 1); } diff --git a/Src/zsh.h b/Src/zsh.h index 2dc5e7e2a..bb8ce130c 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -983,7 +983,8 @@ struct jobfile { struct job { pid_t gleader; /* process group leader of this job */ - pid_t other; /* subjob id or subshell pid */ + pid_t other; /* subjob id (SUPERJOB) + * or subshell pid (SUBJOB) */ int stat; /* see STATs below */ char *pwd; /* current working dir of shell when * * this job was spawned */ @@ -1015,6 +1016,8 @@ struct job { #define STAT_SUBLEADER (0x2000) /* is super-job, but leader is sub-shell */ #define STAT_BUILTIN (0x4000) /* job at tail of pipeline is a builtin */ +#define STAT_SUBJOB_ORPHANED (0x8000) + /* STAT_SUBJOB with STAT_SUPERJOB exited */ #define SP_RUNNING -1 /* fake status for jobs currently running */ |