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

Re: kill the LHS command of a pipe once the RHS command terminates

On Fri, Jun 28, 2019 at 4:05 AM Vincent Lefevre <vincent@xxxxxxxxxx> wrote:
> With some commands I pipe the output to a pager, and when quitting
> the pager, I want the command to terminate immediately (so that it
> doesn't consume more resources) and want the shell prompt back.

This is going to happen in cases where the left-side command doesn't
produce enough output to fill the OS buffer used for the pipe, so it
doesn't see the end-of-file or receive the PIPE signal when the
right-side command closes the other end.  In your examples, you've
also got compound structures that are actually ignoring the state of
their standard output once the small amount of initial output has been
sent.  Neither the shell nor the OS has any way of "knowing" that you
didn't INTEND those commands to continue running.

> Does zsh provide a feature to kill the left-hand-side command in a
> clean way (without a race condition, without a temporary file...)?

That's supposed to be the EOF+SIGPIPE, but it only works for "well
behaved" commands that are actually doing something useful with their
standard output.

In addition to Stephane's suggestions, you can also get control of
your left-side by using "coproc".  This creates an actual job table
entry that you can manipulate.

zsh% coproc { echo foo; sleep 3; echo err >&2 }; head -n 1 <&p; kill %+
[1] 53747
[1]  + terminated  { echo foo; sleep 3; echo err >&2; }

If you're going to kill the right-side with an interrupt or other
signal, you'll have to arrange to trap that so that the subsequent
kill isn't also skipped.  Also in practice you want something more
specific than "kill %+" which could kill the wrong job if you have
multiple backgrounded jobs and the coproc exits before the kill

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