13

Situation:

new_pipe = os.open(pipe_path, os.O_RDONLY | os.O_NONBLOCK) # pipe_path points to a FIFO
data = os.read(new_pipe, 1024)

The read occasionally raises errno -11: Resource temporarily unavailable.

When is this error raised? It seems very rare, as the common cases return data:

  • If no writer has the pipe opened, empty str ('') is returned.
  • If the writer has the pipe opened, but no data is in the fifo, empty str ('') is also returned
  • And of course if the writer puts data in the fifo, that data will be read.
UsAaR33
  • 3,536
  • 2
  • 34
  • 55
  • possible duplicate of [sendto : Resource temporarily unavailable (errno 11)](http://stackoverflow.com/questions/5737493/sendto-resource-temporarily-unavailable-errno-11) – agf Apr 05 '12 at 02:15
  • @agf: The other question is about a sendto erroring, which happens because the send buffer is full. The connection to this particular question is questionable at best, as we are talking about reading Unix pipes here – Niklas B. Apr 05 '12 at 03:11
  • @NiklasB. The question certainly isn't similar, but the answer is. Voting to close as a duplicate was just a convenient way to link to the other question. and get it linked at the top of the sidebar. – agf Apr 05 '12 at 03:14

1 Answers1

12

From the POSIX specification of the read system call (emphasis mine):

When attempting to read from an empty pipe or FIFO:

  • If no process has the pipe open for writing, read() shall return 0 to indicate end-of-file.

  • If some process has the pipe open for writing and O_NONBLOCK is set, read() shall return -1 and set errno to [EAGAIN].

So basically your second assumption is wrong:

If the writer has the pipe opened, but no data is in the fifo, empty str ('') is also returned

This would be against the specification and I can't reproduce that behaviour on my machine (it raises EAGAIN for me). This is not a big problem however, you can just catch the exception and retry:

import errno

def safe_read(fd, size=1024):
   ''' reads data from a pipe and returns `None` on EAGAIN '''
   try:
      return os.read(fd, size)
   except OSError, exc:
      if exc.errno == errno.EAGAIN:
         return None
      raise
Niklas B.
  • 92,950
  • 18
  • 194
  • 224