about summary refs log tree commit diff
path: root/Src/jobs.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2016-09-15 11:42:28 +0100
committerPeter Stephenson <pws@zsh.org>2016-09-16 09:39:33 +0100
commit01ae64c0d74c17e36bfe6f52394a59754b8e8c92 (patch)
tree5c76926c158e8ef5460b86b1c5abc7dbc61a9151 /Src/jobs.c
parentd523ddaba2cd160343b54d3e38ea001c63a87dc6 (diff)
downloadzsh-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/jobs.c')
-rw-r--r--Src/jobs.c11
1 files changed, 9 insertions, 2 deletions
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);
 }