Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't "yes | head" hang?

Why doesn't yes | head hang?

I thought the system collects all of the result from yes and then pipes it to head, and because yes is an infinite loop, the system hangs. But, it can actually stop and show 10 lines of y.

How does the system manage to stop yes when head is done collecting data?

like image 960
Antares Avatar asked Jan 25 '14 12:01

Antares


2 Answers

When you say yes | head the shell will arrange things such that the output of yes goes to a pipe and the input of head comes from that same pipe. When head reads 10 lines, it closes its STDIN_FILENO, thereby closing its end of the pipe. When yes tries to write to a closed pipe it gets a SIGPIPE whose default action is to kill it.

A simple way to test this is with strace:

$ strace yes | head
y
[...]
y
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 4096) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=4069, si_uid=1000} ---
+++ killed by SIGPIPE +++
like image 153
cnicutar Avatar answered Oct 24 '22 22:10

cnicutar


the system collects all of the result from yes and then pipes it to head

That would be extremely inefficient. When you use a pipe, the operating system creates a buffer for the pipe communication.

send | receive

As long as there's enough space in the buffer the sending process will write in it, and if there's enough data in the buffer, the receiver will process it. If there isn't the waiting process is blocked.

As soon as head finishes, the OS notices that it terminated, it will trigger a signal (SIGPIPE) which will terminate the sending process (unless the process handles it).

like image 38
Karoly Horvath Avatar answered Oct 24 '22 22:10

Karoly Horvath