44

When using a pipe for process-process communication, what is the purpose of closing one end of the pipe?

For example: How to send a simple string between two programs using pipes?

Notice that one side of the pipe is closed in the child and parent processes. Why is this required?

Community
  • 1
  • 1
pghazanfari
  • 515
  • 2
  • 6
  • 8

3 Answers3

71

If you connect two processes - parent and child - using a pipe, you create the pipe before the fork.

The fork makes the both processes have access to both ends of the pipe. This is not desirable.

The reading side is supposed to learn that the writer has finished if it notices an EOF condition. This can only happen if all writing sides are closed. So it is best if it closes its writing FD ASAP.

The writer should close its reading FD just in order not to have too many FDs open and thus reaching a maybe existing limit of open FDs. Besides, if the then only reader dies, the writer gets notified about this by getting a SIGPIPE or at least an EPIPE error (depending on how signals are defined). If there are several readers, the writer cannot detect that "the real one" went away, goes on writing and gets stuck as the writing FD blocks in the hope, the "unused" reader will read something.

So here in detail what happens:

  • parent process calls pipe() and gets 2 file descriptors: let's call it rd and wr.
  • parent process calls fork(). Now both processes have a rd and a wr.
  • Suppose the child process is supposed to be the reader.

    Then

    • the parent should close its reading end (for not wasting FDs and for proper detection of dying reader) and
    • the child must close its writing end (in order to be possible to detect the EOF condition).
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • *"each existing reader is supposed to read its data"* - I *think* that is not correct. If a pipe has two readers p1 and p2, and p1 reads some bytes from the pipe, then a read() in p2 will get the next bytes. - All other arguments are correct in my opinion, in particular the EOF detection. – Martin R Oct 09 '13 at 08:02
  • @MartinR mmm... I think you are right. I will change my answer. – glglgl Oct 09 '13 at 08:33
  • A similar argument to the EOF detection can be applied to the writing direction as well: If the reading end is opened *only* in the child process and the child process dies, then writing to the pipe gives EPIPE (or returns an error). This would not work if the reading end is additionally open in the parent process. So it is really a symmetric argument. – Martin R Oct 09 '13 at 08:45
  • @MartinR You are right again. If the "real reader" dies and the "unused" reader is left, the writer doesn't notice that and goes on writing. The writing FD eventually blocks and there is nothing we can do about it again. So another edit. – glglgl Oct 09 '13 at 09:40
  • @kadina Thank you for your comment. Which aspect of it is wrong? – glglgl Jul 11 '15 at 03:23
  • "the child must close its writing end (in order to be possible to detect the EOF condition)", is this true? I can get parent->child communication working without either end closing the write end. – yangmillstheory Nov 12 '17 at 05:37
  • @yangmillstheory "working" is a flexible word. Can you as well detect EOF this way? – glglgl Nov 15 '17 at 09:25
  • @glglgl You're right, my comment was misleading. I can detect an EOF if there's one write from the parent and one read from the child (program will exit), but when the child does a busy read in a loop (exiting only if an EOF is encountered), the writing end of the pipe needs to be closed. Is a special case to the answer that deserves to be called out? – yangmillstheory Nov 15 '17 at 23:52
  • @yangmillstheory I would say that it is quite common to have a reading loop which exits when EOF has been detected (and in other cases). So it is not only a special case, it is the "main case"… – glglgl Nov 16 '17 at 08:53
  • The special case I was talking about above was a single call to `read` outside of a loop. – yangmillstheory Nov 17 '17 at 00:33
  • 1
    @yangmillstheory Yes, in this case you probably don't need it. – glglgl Nov 17 '17 at 08:00
10

The number of file descriptors that can be open at a given time is limited. If you keep opening pipes and not closing them pretty soon you'll run out of FDs and can't open anything anymore: not pipes, not files, not sockets, ...

Another reason why it can be important to close the pipe is when the closing itself has a meaning to the application. For example, a common use of pipes is to send the errno from a child process to the parent when using fork and exec to launch an external program:

  1. The parent creates the pipe, calls fork to create a child process, closes its writing end, and tries to read from the pipe.
  2. The child process attempts to use exec to run a different program:
    1. If exec fails, for example because the program does not exist, the child writes errno to the pipe, and the parent reads it and knows what went wrong, and can tell the user.
    2. If exec is successful the pipe is closed without anything being written. The read function in the parent returns 0 indicating the pipe was closed and knows the program was successfully started.

If the parent did not close its writing end of the pipe before trying to read from the pipe this would not work because the read function would never return when exec is successful.

Joni
  • 108,737
  • 14
  • 143
  • 193
8

Closing unused pipe file descriptor is more than a matter of ensuring that a process doesn't exhaust its limited set of file descriptor-it is essential to the correct use of pipes. We now consider why the unused file descriptors for both the read and write ends of the pipe must be closed. The process reading from the pipe closes its write descriptor for the pipe, so that, when the other process completes its output and closes its write descriptor, the read sees end-of-file (once it has ready any outstanding data in the pipe). If the reading process doesn't close the write end of the pipe, then after the other process closes its write descriptor, the reader won't see end-of-file, even after it has read all data from the pipe. Instead, a read() would block waiting for data, because the kernel knows that there is still at least one write descriptor open for the pipe.That this descriptor is held open by the reading process itself is irrelevant; In theory, that process could still write to the pipe, even if it is blocked trying to read. For example, the read() might be interrupted by a signal handler that writes data to the pipe. The writing process closes its read descriptor for the pipe for a different reason. When a process tries to write to a pipe for which no process has an open read descriptor, the kernel sends the SIGPIPE signal to the writing process. By default, this signal kills a process. A process can instead arrange to catch or ignore this signal, in which case the write() on the pipe fails with the error EPIPE (broken pipe). Receiving the SIGPIPE signal or getting the EPIPE error is useful indication about the status of the pipe, and this is why unused read descriptors for the pipe should be closed. If the writing process doesn't close the read end of the pipe, then even after the other process closes the read end of the pipe, the writing process will fill the pipe, and a further attempt to write will block indefinitely. One final reason for closing unused file descriptor is that only after it all file descriptor are closed that the pipe is destroyed and its resources released for reuse by other processes. At this point, any unread data in the pipe is lost.

~ Micheal Kerrisk , the Linux programming interface

NAND
  • 663
  • 8
  • 22
Holeryn
  • 387
  • 1
  • 4
  • 11