Say we have a named pipe called fifo, and we're reading and writing to it from two different shells. Consider these two examples:
shell 1$ echo foo > fifo
<hangs>
shell 2$ cat fifo
foo
shell 1$ echo bar > fifo
<hangs>
shell 1$ cat > fifo
<typing> foo
<hangs>
shell 2$ cat fifo
foo
^C
shell 1$
<typing> bar
<exits>
I can't wrap my head around what happens in these examples, and in particular why trying to write 'bar' to the pipe in the first example results in a blocking call, whereas in the second example it triggers a SIGPIPE.
I do understand that in the first case, two separate processes write to the pipe, and thus it is opened twice, while in the second case it is only opened once by a single process and written to twice, with the process reading from the pipe being killed in the meantime. What I don't understand is how that affects the behaviour of write.
The pipe(7) man page states:
If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process.
This condition doesn't sound clear to me. A closed file descriptor just ceases to be a file descriptor, right? How does saying "the reading end of the pipe has been closed" differ from "the reading end of the pipe is not open"?
I hope my question was clear enough. By the way, if you could suggest pointers for understanding in details the functioning of Unix pipes in relationship to open, close, read and write operations, I'd greatly appreciate it.