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

Re: How to misplace an entire pipeline

On Sun, 07 Aug 2011 21:05:07 -0700
Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> The following is clearly not a complete fix and maybe is even wrong if
> a different problem is fixed elsewhere, but this at least allows the
> suspended pipeline to be manipulated with jobs/fg/bg/wait.
> --- ../zsh-forge/current/Src/exec.c	2011-07-27 01:13:48.000000000 -0700
> +++ Src/exec.c	2011-08-07 19:07:59.000000000 -0700
> @@ -2845,7 +2845,9 @@
>  	/* This is a current shell procedure that didn't need to fork.    *
>  	 * This includes current shell procedures that are being exec'ed, *
>  	 * as well as null execs.                                         */
> -	jobtab[thisjob].stat |= STAT_CURSH|STAT_NOPRINT;
> +	jobtab[thisjob].stat |= STAT_CURSH;
> +	if (!jobtab[thisjob].procs)
> +	    jobtab[thisjob].stat |= STAT_NOPRINT;
>      } else {
>  	/* This is an exec (real or fake) for an external command.    *
>  	 * Note that any form of exec means that the subshell is fake *

Looks fairly plausible, anyway.
> When "read" is the tail of the pipe, the above all happens behind the
> scenes and then the I/O system call gets restarted, which is how the
> shell ends up stuck.  I'm not sure how to escape from that, except
> maybe to have zhandler() kill the shell with a different signal from
> which the system call will not recover.

I suppose so.  I can hardly believe this ever worked.
> When something like "true" is the tail of the pipe, we return into
> execpline at line 1500 (from waitjobs()), where list_pipe_job is set
> but list_pipe and list_pipe_child are not.  If all three were nonzero,
> a dummy shell would be forked off as PWS described to act as the
> suspended job, but instead execpline() simply returns because the
> last job in the pipeline has exited.
> The only obvious thing I can think to do here is to note in zhandler()
> that we have STAT_CURSH but not list_pipe, and therefore SIGCONT the
> left-hand-side immediately and return as if no signal had occurred
> (possibly printing a warning about not being able to suspend the job,
> which is what happens elsewhere if pipe() or fork() fails).  However,
> that could lead to a serious busy-loop if somehow TTIN or TTOU was
> the signal instead of TSTP.

But we can test if it's TSTP (or STOP)?

There are so many special cases here --- there's one for each state the
current shell might be in during the process, each of which would be
handled straighforwardly if the processing was in another shell --- that
even if it sometimes worked before it's not that surprising if it's
sensitive to knock-on effects.  I suppose it would be nice to be able to
test the things that seem to be working, at least, which would need some
care and probably a bit of extra test framework.

Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/

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