Named pipes, file descriptors and EOF

fifofile-descriptors

Two windows, same user, with bash prompts. In window-1 type:

$ mkfifo f; exec <f

So bash is now attempting to read from file descriptor 0, which is mapped to named pipe f. In window-2 type:

$ echo ls > f

Now window-1 prints an ls and then the shell dies. Why?

Next experiment: open window-1 again with exec <f. In window-2 type:

$ exec 3>f
$ echo ls >&3

After the first line above, window-1 wakes up and prints a prompt. Why? After the second line above, window-1 prints the ls output and the shell stays alive. Why? In fact, now in window-2, echo ls > f does not close the window-1 shell.

The answer must have to do with the existence of the file descriptor 3 from window-2 referencing the named pipe?!

Best Answer

It has to do with the closing of the file descriptor.

In your first example, echo writes to its standard output stream which the shell opens to connect it with f, and when it terminates, its descriptor is closed (by the shell). On the receiving end, the shell, which reads input from its standard input stream (connected to f) reads ls, runs ls and then terminates due to the end-of-file condition on its standard input.

The end-of-file condition occurs because all writers to the named pipe (only one in this example) have closed their end of the pipe.

In your second example, exec 3>f opens file descriptor 3 for writing to f, then echo writes ls to it. It's the shell that now has the file descriptor opened, not the echo command. The descriptor remains open until you do exec 3>&-. On the receiving end, the shell, which reads input from its standard input stream (connected to f) reads ls, runs ls and then waits for more input (since the stream is still open).

The stream remains open because all writers to it (the shell, via exec 3>f, and echo) have not closed their end of the pipe (exec 3>f is still in effect).


I have written about echo above as if it was an external command. It's most likely is built into the shell. The effect is the same nonetheless.