Firecracker v0.24.2 has been released which handles SIGPIPE. I was working on that this week.

TCP/IP, Sockets, and SIGPIPE (2018) is a good read. The author mostly focuses the fact that TCP socket APIs were based on pipes, so pipes’ behaviors were automatically inherited.

But, even regarding pipes, SIGPIPE is weird. Writing to files would fail but it won’t kill a program. Why do we want to kill a program only for pipes?

There is a Stack Overflow question with some answers. The most accepted one is;

I believe the reason SIGPIPE exists is much simpler: establishing sane default behavior for pure “filter” programs that continuously read input, transform it somehow, and write output.

Which, somewhat makes sense.

In terms of history, Unix v6 had signal(2) with 13 – “write on a pipe with no one to read it”. At that time, all signals didn’t have names and only defined as numbers. Unix v1 didn’t have any signals. doesn’t have Unix v5’s man pages, but the Unix Heritage Society has Unix Programmer’s Manual’s scanned PDF. According to the PDF, page 159, Unix v5 had signal(2) but didn’t have 13. So SIGPIPE was introduced as the part of Unix v6.

Interestingly Rust ignores SIGPIPE due to the fact it had green threads before. The ship has sailed and people don’t want to change the behavior anymore. Go ignores SIGPIPE too only if the file descriptor is neither stdout nor stderr.