Какие условия приводят к тому, что открытый неблокирующий именованный канал (fifo) становится недоступным для чтения?

Ситуация:

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

При чтении иногда возникает ошибка -11: ресурс временно недоступен.

Когда возникает эта ошибка? Это кажется очень редким, поскольку в общих случаях возвращаются данные:

  • Если ни один писатель не открыл канал, возвращается пустая строка str ('').
  • Если канал записи был открыт, но в FIFO нет данных, также возвращается пустая строка str ('').
  • И, конечно, если писатель помещает данные в FIFO, эти данные будут прочитаны.

person UsAaR33    schedule 05.04.2012    source источник
comment
возможный дубликат sendto: ресурс временно недоступен (ошибка 11)   -  person agf    schedule 05.04.2012
comment
@agf: Другой вопрос касается ошибки sendto, которая происходит из-за переполнения буфера отправки. Связь с этим конкретным вопросом в лучшем случае сомнительна, поскольку здесь мы говорим о чтении каналов Unix.   -  person Niklas B.    schedule 05.04.2012
comment
@NiklasB. Вопрос, конечно, не похож, но ответ есть. Голосование за закрытие дубликата было просто удобным способом связать другой вопрос. и свяжите его в верхней части боковой панели.   -  person agf    schedule 05.04.2012


Ответы (1)


Из спецификации POSIX системного вызова read (выделено мной):

При попытке чтения из пустого канала или FIFO:

  • Если ни один процесс не открыл канал для записи, read () должен вернуть 0, чтобы указать конец файла.

  • Если у некоторого процесса канал открыт для записи и установлено значение O_NONBLOCK, функция read () вернет -1 и установит для errno значение [EAGAIN].

Итак, в основном ваше второе предположение неверно:

Если канал записи был открыт, но в FIFO нет данных, также возвращается пустая строка str ('').

Это противоречит спецификации, и я не могу воспроизвести такое поведение на своей машине (для меня это повышает EAGAIN). Однако это не большая проблема, вы можете просто поймать исключение и повторить попытку:

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
person Niklas B.    schedule 05.04.2012
comment
Большое спасибо. Похоже, у меня действительно были ошибки в моем собственном тестовом коде! - person UsAaR33; 05.04.2012