2
votes

I have two processes created with named pipe. The writer process writes a message using write(), and the reader process reads the message with read(). I noticed that read() blocks when the writer closes the pipe. Is that possible to let writer process sends EOF before closing the pipe so that the reader will not be blocked?

2
If the writer closes its end of the pipe, read on the other end should return 0. Can you please show your reader code, or at least try to create a Minimal, Complete, and Verifiable Example of the reader to show us what you do? - Some programmer dude
read() returns 0 when the last file desriptor on the write end has been closed. The man page remarks that after a fork() the processes should close() unused file descriptors, because leaving them open would not cause EOF on the reader side resp. SIGPIPE on the writer side as one would expect when the actual writers/readers close the pipe fd. Could that be an issue? - Peter - Reinstate Monica

2 Answers

2
votes

Not... It's not possible to send an EOF because EOF is nothing that maps to something sent over the channel. EOF condition (yes, it's a condition, not something you receive or send over the channel) means there's no more data to read(2) and it's got by a process by making read(2) to return 0 characters read. As many reads you do in EOF condition, they will return a value of 0 meaning there's no more data.

By the way, pipes block readers when there's no data available, but, as the writer is still there to send more data, there's no EOF condition. By design, pipes block readers when there's no data available (but a writer still has the pipe open) and block writers when there's no more space to put data in the fifo (this happens when there are readers with the fifo open, but none of them is reading) As you see it's a feature, not a bug.

If you want to make read(2) non blocking and get 0 when there's no data available, you can open(2) with O_NONBLOCK flag (or do it later, with the fcntl(2) system call), that will make read(2) to return immediately with the available data (even if there's no data available) but it has a drawback: then you cannot distinguish a fifo with no data available (it has not been written) from an actual EOF (the writer has closed its side) as both will return with 0 as result.

By the way, I don't like to use the EOF constant when talking about end of file conditions, because it adds to the confusion of its definition. EOF is the value returned by getchar(3) on an end of file condition, but it's not a char (if you check the definition of getchar(3) you will discover it's defined as int and not char, this is to add the EOF condition to the whole range of possible char values --- so, there are 257 possible values returned from getchar(3), 0-256 for data, and EOF for end of file condition)

If you want writers to signal end of file they have to close(2) the fifo and reopen it.

1
votes

When the writer closes the pipe, the reader will not block, even if it was blocked (e.g. it will wake up). The read call will return 0 indicating EOF on the pipe. The reader should do:

rlen = read(pipefd,buf,sizeof(buf));
if (rlen <= 0)
    break;

Are you checking your return codes?

In the writer, if the reader has closed the pipe prematurely (e.g. it aborted), the writer will get a return from write of -1 and errno set to EPIPE. It can also get SIGPIPE.

See man 7 pipe ...