mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
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.
This commit is contained in:
parent
d523ddaba2
commit
01ae64c0d7
4 changed files with 38 additions and 4 deletions
|
@ -1,3 +1,10 @@
|
|||
2016-09-16 Peter Stephenson <p.stephenson@samsung.com>
|
||||
|
||||
* 39331: Src/exec.c, Src/jobs.c, Src/zsh.h: Partially fix problem
|
||||
occurring when a subjop in the RHS of a pipeline needs to be
|
||||
picked up by a forked zsh after ^Z when the original superjob
|
||||
(LHS of pipeline) has already exited. Still race-prone.
|
||||
|
||||
2016-09-16 Daniel Shahaf <d.s@daniel.shahaf.name>
|
||||
|
||||
* unposted: Completion/Unix/Command/_postfix: Correct quoting
|
||||
|
|
19
Src/exec.c
19
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);
|
||||
|
|
11
Src/jobs.c
11
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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue