2
votes

I have a C program that writes data to a named pipe and a Python program that reads data from the named pipe, like this:

p = open('/path/to/named/pipe', 'r')
...
data = p.read(size)

When the C program exits, it closes the pipe.

How can I detect this from the Python side? I've tried installing a handler for SIGPIPE, but it seems that SIGPIPE only happens when attempting to write to a closed pipe, not read from it. I also expected that p.read(size) might return a length-zero string because of the EOF at the other end, but actually it just hangs waiting for data.

How can I detect this situation and handle it?

1
If the Python is hanging around, it almost certainly means some process, possibly itself, still has the pipe open for writing. If all the writers close the pipe, all the readers (normally, 'all' is just one reader) will get EOF on their next attempt to read. Note that if the Python opens the pipe for read and write, it is a writer and will never get EOF. - Jonathan Leffler
You can place nonblock for that file descriptor. - Karthikeyan.R.S
I think the problem here is that using open(...,'r') doesn't do the right thing; it's necessary to use os.open(..., os.O_RDONLY). - Tom

1 Answers

0
votes

You can use the select module to monitor the state of your pipe. On Linux (where select.poll() is available, the following code will detect the presence of a closed pipe:

import select

# ...

poller = select.poll()
# Register the "hangup" event on p
poller.register(p, select.POLLHUP)

# Call poller.poll with 0s as timeout
for descriptor, mask in poller.poll(0):
    # Can contain at most one element, but still:
    if descriptor == p.fileno() and mask & select.POLLHUP:
        print('The pipe is closed on the other end.')
        p.close()

Analogous methods exist for other OS as well that can detect such situations.

The reason why it hangs when calling read, is because the IO is blocking. You can turn it into non-blocking (and have read return an empty string) by using os.set_blocking, but this would still not allow you to detect when the pipe on the other end is closed.