about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--NEWS7
-rw-r--r--Src/jobs.c15
3 files changed, 22 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index b66b7e2be..28ddd557a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-08-22  Barton E. Schaefer  <schaefer@zsh.org>
+
+	* 33042: NEWS, Src/jobs.c: $? and $pipestatus report 128+signal
+	number for stopped jobs as well as terminated jobs
+
 2014-08-20  Barton E. Schaefer  <schaefer@zsh.org>
 
 	* Lokesh Mandvekar: 33032: Completion/Linux/Command/_docker,
diff --git a/NEWS b/NEWS
index 3a761b1e2..1f2a9daad 100644
--- a/NEWS
+++ b/NEWS
@@ -84,6 +84,13 @@ Changes since 5.0.0
   longer array is trimmed whereas the :^^ operator repeats the shorter
   array enough to match the longer array.
 
+- The value of $? when a job becomes stopped is now the signal number plus
+  128, for compatibility with other shells.  Note that different operating
+  systems use different values e.g. for SIGTSTP, so it is not possible in
+  portable scripts to detect stopped jobs by comparing to a fixed number.
+  Also, the value of $pipestatus is now updated when a job stops, not just
+  when it exits.
+
 Changes between 4.2 and 5.0.0
 -----------------------------
 
diff --git a/Src/jobs.c b/Src/jobs.c
index c4a0707d4..83a4d96a4 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -384,9 +384,11 @@ storepipestats(Job jn, int inforeground, int fixlastval)
     Process p;
 
     for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++) {
-	jpipestats[i] = ((WIFSIGNALED(p->status)) ?
+	jpipestats[i] = (WIFSIGNALED(p->status) ?
 			 0200 | WTERMSIG(p->status) :
-			 WEXITSTATUS(p->status));
+			 (WIFSTOPPED(p->status) ?
+			  0200 | WEXITSTATUS(p->status) :
+			  WEXITSTATUS(p->status)));
 	if (jpipestats[i])
 	    pipefail = jpipestats[i];
     }
@@ -436,8 +438,11 @@ update_job(Job jn)
 	if (WIFSTOPPED(pn->status))        /* some processes are stopped                   */
 	    somestopped = 1;               /* so job is not done, but entry needs updating */
 	if (!pn->next)                     /* last job in pipeline determines exit status  */
-	    val = (WIFSIGNALED(pn->status)) ? 0200 | WTERMSIG(pn->status) :
-		WEXITSTATUS(pn->status);
+	    val = (WIFSIGNALED(pn->status) ?
+		   0200 | WTERMSIG(pn->status) :
+		   (WIFSTOPPED(pn->status) ?
+		    0200 | WEXITSTATUS(pn->status) :
+		    WEXITSTATUS(pn->status)));
 	if (pn->pid == jn->gleader)        /* if this process is process group leader      */
 	    status = pn->status;
     }
@@ -537,7 +542,7 @@ update_job(Job jn)
 	return;
     jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
 	STAT_CHANGED | STAT_DONE;
-    if (jn->stat & STAT_DONE) {
+    if (jn->stat & (STAT_DONE|STAT_STOPPED)) {
 	/* This may be redundant with printjob() but note that inforeground
 	 * is true here for STAT_CURSH jobs even when job != thisjob, most
 	 * likely because thisjob = -1 from exec.c:execsimple() trickery.