about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>2022-06-03 19:32:56 +0900
committerJun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>2022-06-03 19:32:56 +0900
commit22b1a91c2a07e6d6a57975a1ab47d66f92aa21f2 (patch)
tree3c6a40302e7ba513f75aa10b918793d56abcf5f6
parent8756cc6add3d27d05e869fc7317e3043ab2be5b2 (diff)
downloadzsh-22b1a91c2a07e6d6a57975a1ab47d66f92aa21f2.tar.gz
zsh-22b1a91c2a07e6d6a57975a1ab47d66f92aa21f2.tar.xz
zsh-22b1a91c2a07e6d6a57975a1ab47d66f92aa21f2.zip
50306: fix wait for child that was stopped/continued
do not call addbgstatus() when child is stopped/continued
-rw-r--r--ChangeLog5
-rw-r--r--Src/jobs.c20
-rw-r--r--Src/signals.c10
-rw-r--r--Test/A05execution.ztst7
4 files changed, 34 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 43a805bc7..780f967f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2022-06-03  Jun-ichi Takimoto  <takimoto-j@kba.biglobe.ne.jp>
+
+	* 50306: Src/jobs.c, Src/signals.c, Test/A05execution.ztst: fix
+	wait builtin for child that has been stopped and continued.
+
 2022-05-30  Bart Schaefer  <schaefer@zsh.org>
 
 	* Marlon Richert: 50307 (cf. PWS 50205):
diff --git a/Src/jobs.c b/Src/jobs.c
index a91ef787f..aa32f4e80 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -414,7 +414,7 @@ storepipestats(Job jn, int inforeground, int fixlastval)
 	jpipestats[i] = (WIFSIGNALED(p->status) ?
 			 0200 | WTERMSIG(p->status) :
 			 (WIFSTOPPED(p->status) ?
-			  0200 | WEXITSTATUS(p->status) :
+			  0200 | WSTOPSIG(p->status) :
 			  WEXITSTATUS(p->status)));
 	if (jpipestats[i])
 	    pipefail = jpipestats[i];
@@ -471,7 +471,7 @@ update_job(Job jn)
 	    val = (WIFSIGNALED(pn->status) ?
 		   0200 | WTERMSIG(pn->status) :
 		   (WIFSTOPPED(pn->status) ?
-		    0200 | WEXITSTATUS(pn->status) :
+		    0200 | WSTOPSIG(pn->status) :
 		    WEXITSTATUS(pn->status)));
 	    signalled = WIFSIGNALED(pn->status);
 	}
@@ -2221,6 +2221,7 @@ addbgstatus(pid_t pid, int status)
 {
     static long child_max;
     Bgstatus bgstatus_entry;
+    LinkNode node;
 
     if (!child_max) {
 #ifdef _SC_CHILD_MAX
@@ -2244,6 +2245,21 @@ addbgstatus(pid_t pid, int status)
 	if (!bgstatus_list)
 	    return;
     }
+#ifdef DEBUG
+    /* See if an entry already exists for the pid */
+    for (node = firstnode(bgstatus_list); node; incnode(node)) {
+	bgstatus_entry = (Bgstatus)getdata(node);
+	if (bgstatus_entry->pid == pid) {
+	    /* In theory this should not happen because addbgstatus() is
+	     * called only once when the process exits or gets killed. */
+	    dputs("addbgstatus called again: pid %d: status %d -> %d",
+		    pid, bgstatus_entry->status, status);
+	    bgstatus_entry->status = status;
+	    return;
+	}
+    }
+#endif
+    /* Add an entry for the pid */
     if (bgstatus_count == child_max) {
 	/* Overflow.  List is in order, remove first */
 	rembgstatus(firstnode(bgstatus_list));
diff --git a/Src/signals.c b/Src/signals.c
index 5c787e2a8..a61368554 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -576,12 +576,10 @@ wait_for_processes(void)
 	 */
 	if (jn && !(jn->stat & (STAT_CURSH|STAT_BUILTIN)) &&
 	    jn - jobtab != thisjob) {
-	    int val = (WIFSIGNALED(status) ?
-		   0200 | WTERMSIG(status) :
-		   (WIFSTOPPED(status) ?
-		    0200 | WEXITSTATUS(status) :
-		    WEXITSTATUS(status)));
-	    addbgstatus(pid, val);
+	    if (WIFEXITED(status))
+		addbgstatus(pid, WEXITSTATUS(status));
+	    else if (WIFSIGNALED(status))
+		addbgstatus(pid, 0200 | WTERMSIG(status));
 	}
 
 	unqueue_signals();
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index d95ee363c..b257ddf2c 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -396,6 +396,13 @@ F:anonymous function, and a descriptor leak when backgrounding a pipeline
 # TBD: the 0 above is believed to be bogus and should also be turned
 # into 127 when the ccorresponding bug is fixed in the main shell.
 
+  sleep 1 & pid=$!
+  kill -STOP $pid
+  sleep 1
+  kill -CONT $pid
+  wait $pid
+0:wait for stopped and continued process
+
 # Without the outer subshell, the test harness reports the pre-46060 behaviour
 # as "skipped" rather than "failed".
  (( exit 130 ) | { sleep 1; echo hello })