Question Details

No question body available.

Tags

haskell functional-programming pipe blocking mkfifo

Answers (2)

Accepted Answer Available
Accepted Answer
October 8, 2025 Score: 7 Rep: 52,949 Quality: Expert Completeness: 60%

Per the fifo(7) and pipe(7) manpages, when a fifo is opened for reading in (default) blocking mode, the open call will block until a writer also opens the fifo (and vice versa). Reading from a fifo opened in blocking mode will block until data becomes available (which will return the data) or there are no writers who have the fifo open (which will return EOF). So, if you use cat, which opens the fifo in blocking mode, it will block until the writer opens the fifo, and will read data until the writer closes the file and the cat process gets an EOF.

The Haskell readFile function, like the openFile function, opens a file in non-blocking mode. For a fifo, this means that the open call returns immediately. Reading from a fifo opened in non-blocking mode will return an EAGAIN "error" if there is no data but there are writers holding the fifo open, and it will return EOF if there are no writers holding the fifo open. When Haskell reads from the fifo (or any file), it does so using normal non-blocking I/O semantics, so if there are writers available and it gets an EAGAIN error, it knows to use poll for more data. But, if it reads from a fifo with no writers available, it gets an EOF and -- in the case of readFile -- returns an empty string.

GHC has openFileBlocking and withFileBlocking functions that you can use:

import System.IO
import GHC.IO.Handle.FD
main = openFileBlocking "/tmp/foo" ReadMode >>= hGetContents >>= putStr

This version will block on the open call and wait for the writer to join.

October 8, 2025 Score: 1 Rep: 55,484 Quality: Low Completeness: 40%

This is a property of the FIFO, not of readFile. If there are no open writers, reading to the end of the file will return immediately instead of blocking. This is so that a FIFO cooperates better with programs that only know how to deal with ordinary files.

If you want to block anyway, I believe you need to do what e.g. tail --follow does: wait for changes by polling (fstat) or listening (inotify), and reopen the input as needed.