pipe · read · write · close
The buffer is 64K, and that is the bug
A pipe holds a finite number of bytes. A writer that fills it blocks, and a reader that is waiting for the writer to exit first will wait forever.
A pipe is not a queue
A pipe holds about sixty-four kilobytes. Writing more than that does not fail and does not grow the buffer — the writer blocks, inside the write, until somebody reads.
This is the mechanism behind the most common way a subprocess call hangs. The parent starts a child with its output on a pipe, waits for it to exit, and then reads. The child fills the buffer, blocks in write, and never exits. The parent waits for a process that is waiting for the parent. Neither moves again.
It works perfectly on small output. Nothing in either program mentions sixty-four thousand anything.
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
int fds[2];
char big[100000];
pipe(fds);
pid_t pid = fork();
if (pid == 0) {
close(fds[0]);
write(fds[1], big, 100000);
_exit(0);
}
close(fds[1]);
int status;
waitpid(pid, &status, 0);
return 0;
}Watch: Both calls left open at the end of the trace, and what the machine says stopped it.
The ends nobody closes
pipe gives both ends to one process, and after fork both processes have both. That is four descriptors on two ends, and every one of them counts.
A reader sees end-of-file when every writer has closed. If the parent forgot to close its own copy of the write end, there is still a writer — itself — and the read waits forever for a byte that is never coming.
A writer gets EPIPE, and a SIGPIPE that kills it by default, when every reader has closed. That asymmetry is why yes | head -1 terminates instead of running until the disk fills.
Predict
A parent forks a child to write to a pipe, and the parent reads. The parent does not close its own write end. What happens?