Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Odd job-reporting buglet (Re: Change in suspend behavior)



Bart Schaefer wrote:

> ...
> 
> Change that loop just a little bit and some really strange things happen:
> 
> schaefer[501] for i in bar foo; do cat & wait; done
> [2] 27451
> [2]  + suspended (tty input)  cat
> [1] 27452
> [1]  + suspended (tty input)  cat
> zsh: suspended (tty input)  cat | 
> zsh: running                for i in bar foo; do; cat & wait; done
> 
> Eh?  It thinks "cat" has been piped to the for loop!  Also, how did job
> number 2 get a smaller process ID than job number 1?
> 
> schaefer[502] jobs -l
> [1]  + 27452 suspended (tty input)  cat | 
>        27453 running                for i in bar foo; do; cat & wait; done
> [2]  - 27451 suspended (tty input)  cat

Aaarrrrggghhh!

The reason is pretty clear (to some): the sub-job returns and is
stopped, so execpline() things it has to do all that super/sub-job
handling it does when the sub-job was suspended with ^Z.

One way to try to fix this is to make execpline() check if the sub-job
really was suspended because of a ^Z (SIGTSTP).  And only then create a
super-job and whatnot.

The other way to try to fix this would be to check if the sub-job was
ASYNC (i.e. it had a `&' at the end), pass that information up to (the
right) execpline() and there decide to not wrap it into a super-job.

The patch below (not committed and certainly not to be committed before
we've discussed this some more) does the first for me (check for SIGTSTP).

I think both solutions have their pros and cons.  Opinions?

Bye
  Sven

Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.26
diff -u -r1.26 exec.c
--- Src/exec.c	2001/03/30 16:51:54	1.26
+++ Src/exec.c	2001/05/11 08:47:30
@@ -1064,11 +1064,26 @@
 		    jn->stat & STAT_DONE &&
 		    lastval2 & 0200)
 		    killpg(mypgrp, lastval2 & ~0200);
+#if 0
+                /* This does the wrong thing if the sub-job was stopped
+                 * for some other reason than the user hitting ^Z.  In that
+                 * case we don't want it to put the whole loop (or whatever)
+                 * into a super-job. */
 		if (!list_pipe_child && !lpforked && !subsh && jobbing &&
 		    (list_pipe || last1 || pline_level) &&
 		    ((jn->stat & STAT_STOPPED) ||
 		     (list_pipe_job && pline_level &&
 		      (jobtab[list_pipe_job].stat & STAT_STOPPED)))) {
+#endif
+		if (!list_pipe_child && !lpforked && !subsh && jobbing &&
+		    (list_pipe || last1 || pline_level) &&
+		    (((jn->stat & STAT_STOPPED) &&
+                      WIFSTOPPED(jn->procs->status) &&
+                      WSTOPSIG(jn->procs->status) == SIGTSTP) ||
+		     (list_pipe_job && pline_level &&
+		      (jobtab[list_pipe_job].stat & STAT_STOPPED) &&
+                      WIFSTOPPED(jobtab[list_pipe_job].procs->status) &&
+                      WSTOPSIG(jobtab[list_pipe_job].procs->status) == SIGTSTP))) {
 		    pid_t pid;
 		    int synch[2];
 

-- 
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author