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

Re: $pipestatus broken?



On Dec 23, 11:11pm, Frank Terbeck wrote:
}
} ...unless, of course, the loop just needs to be there to delay the RHS,
} for the exit/reap to happen as you suggested.

Hmm, this is getting a bit hairy.

In the simple case { echo foo | read -E }, there is a single job table
entry for "read" which is the group leader for the pipeline.

In the loop case { echo foo | repeat 1; read -E } there is a job table
entry for the loop which is the group leader, but a new entry is
created for "read -E".  execpline() remembers the previous thisjob as
the local "pj" and restores thisjob = pj at line 1619, but by that
time it is too late -- waitjobs() has set thisjob = -1 for just long
enough for zhandler() to call update_job(), which fails to update the
pipestats because thisjob = -1 tells it there is no current job.

The following seems to fix it, by telling waitjobs() what the previous
job number was so it can be reset immediately.  There may still be a
race condition that requires fiddling with signal blocks to make sure
thisjob is correct at the time the zhandler() catches the signal, but
if so this should at least allow the block/unblock to be localized.

Index: Src/exec.c
===================================================================
--- Src/exec.c	20 Dec 2011 17:13:38 -0000	1.43
+++ Src/exec.c	24 Dec 2011 09:22:57 -0000
@@ -1516,7 +1516,7 @@
 		}
 		if (!(jn->stat & STAT_LOCKED)) {
 		    updated = hasprocs(thisjob);
-		    waitjobs();
+		    waitjobs(pj);
 		    child_block();
 		} else
 		    updated = 0;
@@ -3339,7 +3339,7 @@
 		close(i);
 	closem(FDT_UNUSED);
 	if (thisjob != -1)
-	    waitjobs();
+	    waitjobs(-1);
 	_exit(lastval);
     }
     fixfds(save);
Index: Src/jobs.c
===================================================================
--- Src/jobs.c	20 Dec 2011 17:13:38 -0000	1.31
+++ Src/jobs.c	24 Dec 2011 09:23:34 -0000
@@ -1363,7 +1363,7 @@
 
 /**/
 void
-waitjobs(void)
+waitjobs(int prevjob)
 {
     Job jn = jobtab + thisjob;
     DPUTS(thisjob == -1, "No valid job in waitjobs.");
@@ -1375,7 +1375,7 @@
 	pipestats[0] = lastval;
 	numpipestats = 1;
     }
-    thisjob = -1;
+    thisjob = prevjob;
 }
 
 /* clear job table when entering subshells */
@@ -2072,7 +2072,7 @@
 		 * when we've just been told to wait for another
 		 * job (and done it)?
 		 */
-		waitjobs();
+		waitjobs(-1);
 		retval = lastval2;
 	    } else if (ofunc == BIN_DISOWN)
 	        deletejob(jobtab + job, 1);



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