3

I am trying to better understand SIGPIPE on linux.

I ran this experiment: { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head and it echos 141 which I understand is an exit code that is given to processes that exit with SIGPIPE Previously, I have done this a lot without understanding the nuances of SIGPIPE and I usually run with set -eEuo pipefail so, I was trying to understand why my code wasn't failing all the time due to broken pipes... So I ran this other experiment: ( set -o pipefail; { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head; ) and I got a 0 in the echo that time... so when pipefail is enabled, does that mean that SIGPIPE is suppressed? or am I misunderstanding what is going on here?

1 Answer 1

6

ls may manage to write all its output before head exits and breaks the pipe, even if the output of ls is longer than what head prints. This is because:

  • head may read more than it will eventually print,
  • and there is a buffer for the pipe anyway.

SIGPIPE is triggered by actual writing to a broken pipe. If ls manages to write all its output before head exits then there will be no act of writing that triggers SIGPIPE.

Or ls may fail to manage to write all its output before head exits. Then it will try to write more and it will get SIGPIPE.

As ls and head run in parallel, I think in general there is a race condition. It may happen that some particular output from ls does or does not trigger SIGPIPE, randomly.

Try with yes instead of ls …:

{ yes ; echo "$?" 1>&2 ; } | head

or

( set -o pipefail; { yes ; echo "$?" 1>&2 ; } | head; )

yes generates output that does not end by itself, so after head exits there will always be an act of writing that triggers SIGPIPE. Each of the above commands will give you 141 for sure.

This has nothing to do with pipefail.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .