summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Src/exec.c19
-rw-r--r--Src/jobs.c11
-rw-r--r--Src/zsh.h5
4 files changed, 38 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 0d130b040..29796ed01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
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 */