zsh-workers
 help / color / mirror / code / Atom feed
* $? and suspended jobs
@ 2014-08-21 19:37 Stephane Chazelas
  2014-08-21 21:31 ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Stephane Chazelas @ 2014-08-21 19:37 UTC (permalink / raw)
  To: zsh-workers

~$ sleep 4; echo $?, $pipestatus
^Z
zsh: suspended  sleep 4
20, 0


Why not 128+20 = 148? I'd expect $pipestatus to contain the same
value as $?

~$ {sleep 5; echo $?}
^Zzsh: suspended  { sleep 5; echo $?; }
(20)1~$ fg
[1]  + continued  { sleep 5; echo $?; }
20

(that "(20)" is $? in my prompt). Here `echo $?` is run after sleep
finishing and returning a 0 exit status. Still $? is always
based on SIGTSTP.

~$ {(sleep 5; echo "$?"; exit 12); echo $?, $pipestatus}
^Zzsh: suspended  { ( sleep 5; echo "$?"; exit 12; ); echo $?, $pipestatus; }
(20)1~$ fg
[1]  + continued  { ( sleep 5; echo "$?"; exit 12; ); echo $?, $pipestatus; }
0
20, 0

$? is always 20 and $pipestatus always 0 regardless of the exit
status of the command that is resumed.

You might say there's value in that (one may want to consider a
command that was suspended as having failed), but the behaviour
is quite surprising.

Spawned from a question at:
http://unix.stackexchange.com/questions/151376/how-do-i-gracefully-suspend-and-resume-cmd1-cmd2-cmd3-chain

-- 
Stephane


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: $? and suspended jobs
  2014-08-21 19:37 $? and suspended jobs Stephane Chazelas
@ 2014-08-21 21:31 ` Bart Schaefer
  2014-08-22  1:45   ` [PATCH] " Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Bart Schaefer @ 2014-08-21 21:31 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1479 bytes --]

On Aug 21, 2014 12:58 PM, "Stephane Chazelas" <stephane.chazelas@gmail.com>
wrote:
>
> ~$ sleep 4; echo $?, $pipestatus
> ^Z
> zsh: suspended  sleep 4
> 20, 0
>
>
> Why not 128+20 = 148? I'd expect $pipestatus to contain the same
> value as $?

The values in the $pipestatus array are only updated when a process
completes, and a stopped job hasn't completed yet.  (I'm reporting a fact
here, not stating opinion on whether it should be this way.)

As for $?, as best I can tell the WIFSIGNALED() test returns false for the
exit status of a stopped job, so zsh doesn't add 128 to the status, but it
does apply the WEXITSTATUS() filter which removes the WIFSTOPPED() bits
leaving just the signal number.  This is, at least, incompatible with bash.

>
> ~$ {sleep 5; echo $?}
> ^Zzsh: suspended  { sleep 5; echo $?; }
> (20)1~$ fg
> [1]  + continued  { sleep 5; echo $?; }
> 20
>
> (that "(20)" is $? in my prompt). Here `echo $?` is run after sleep
> finishing and returning a 0 exit status. Still $? is always
> based on SIGTSTP.

Sleep is weird because it doesn't resume sleeping after being TSTP'd, it
just exits when CONT'd.  Also in that case you aren't just stopping sleep,
you're stopping the entire brace expression, which forces it to transform
from a current-shell job into a subshell. Hence there's a race and you
can't actually be sure that $? was set after sleep resumed.

Adding more layers of parens and braces just makes the order of events even
less predictable.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] Re: $? and suspended jobs
  2014-08-21 21:31 ` Bart Schaefer
@ 2014-08-22  1:45   ` Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 2014-08-22  1:45 UTC (permalink / raw)
  To: Zsh hackers list

On Aug 21,  2:31pm, Bart Schaefer wrote:
}
} The values in the $pipestatus array are only updated when a process
} completes, and a stopped job hasn't completed yet.  (I'm reporting a fact
} here, not stating opinion on whether it should be this way.)
} 
} As for $?, as best I can tell the WIFSIGNALED() test returns false for the
} exit status of a stopped job, so zsh doesn't add 128 to the status, but it
} does apply the WEXITSTATUS() filter which removes the WIFSTOPPED() bits
} leaving just the signal number.  This is, at least, incompatible with bash.

The patch below changes both of these things, that is, it adds 128 to the
signal number even on stop signals, and it sets $pipestatus on stop as well
as on termination.  If the latter isn't wanted, revert the third hunk of
the patch.


diff --git a/Src/jobs.c b/Src/jobs.c
index c4a0707..83a4d96 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.



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-08-22  1:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-21 19:37 $? and suspended jobs Stephane Chazelas
2014-08-21 21:31 ` Bart Schaefer
2014-08-22  1:45   ` [PATCH] " Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).