24

Some programs can have an infinite runtime and produce infinite output. When used in a pipe with a command that finish, how does the pipeline knows when to stop ?

For instance, take yes (infinite output) with head:

 yes | head -n 5

It will only yield 5 y.

Is the first command that end the one that stop the other processes input/output ?
How does it works ?

Cyrbil
  • 389
  • 1
  • 4
  • 10

1 Answers1

29

The commands are connected with a pipe (I'm talking the system primitive here—obviously, they're connected with a |). When the read end of the pipe (the stdin of head) becomes closed (== when head either explicitly (close) or implicitly (exit) closes it), attempts to write to the write end (stdout of yes) will fail.

By default, this is not just a regular errno failure, but a failure that results in the writing process receiving the SIGPIPE signal. The default handler action of the SIGPIPE signal is to terminate.

In short—if you write to a broken pipe, the system will send you a SIGPIPE and by default, a SIGPIPE will kill you. That is why yes terminates when head has ended (and thereby broken the pipe).


If you ignore SIGPIPE in the parent shell, then the commands will inherit this disposition and a write to a broken pipe will simply cause an errno error of EPIPE. As it appears, yes stringifies this error an prints it:

$ (trap "" SIGPIPE; yes | head -n 5)  
y
y
y
y
yes: standard output: Broken pipe
yes: write error
Petr Skocik
  • 28,816
  • 1
    That was exaclty the answer I was looking for. So a part of a pipe can terminate but the other continue (if SIGPIPE is ignored) ? Have you an example in mind ? – Cyrbil Mar 08 '16 at 09:58
  • @Cyrbil In the example with the trap, yes exits purely voluntarily. Consider a pipeline where the writer is a while loop: (trap "" SIGPIPE; while : ; do echo a; echo b >&2; sleep 0.2; done | head -n 5)—it goes happily on except echo a; will only succeed 5 times. Similarly, the reader end can close its stdin explicitly (in C by doing close(0);, in shell by doing exec 0>&-)(probably causing the writer process to die from SIGPIPE) rather than implicitly (=by exitting) and continue . – Petr Skocik Mar 08 '16 at 11:13