Haskell writing to named pipe unexpectedly fails with `openFile: does not exist (No such device or address)`

31 views Asked by At

If I created a named pipe with mkfifo /tmp2/example and use the following function:

writeToFifo :: FilePath -> IO ()
writeToFifo path = do
  handle <- openFile path WriteMode
  let loop n = do
        let msg = "Message " ++ show n
        hPutStrLn handle msg
        hFlush handle
        putStrLn $ "Wrote: " ++ msg
        threadDelay 1000000  -- Sleep for 1 second
        loop (n + 1)
  loop (1 :: Int)

But that results in * Exception: /tmp2/example: openFile: does not exist (No such device or address)

Even though it exists

ls -alrth /tmp2/example
prw------- 1 chris users 0 Mar 30 12:54 /tmp2/example

Why does this happen? How do I fix it?

1

There are 1 answers

0
Chris Stryczynski On

This is due to the way openFile is implemented with file blocking as described here https://gitlab.haskell.org/ghc/ghc/-/issues/15715.

Can be fixed with:

import GHC.IO.Handle.FD (openFileBlocking)

And replace openFile with openFileBlocking.

Alternatively:


writeToFifo :: FilePath -> IO ()
writeToFifo path = do
  -- Open the FIFO for writing, without creating it (assumes it exists)
  fd <- openFd path WriteOnly Nothing defaultFileFlags
  handle <- fdToHandle fd
  let loop n = do
        let msg = "Message " ++ show n
        hPutStrLn handle msg
        hFlush handle
        putStrLn $ "Wrote: " ++ msg
        threadDelay 1000000  -- Sleep for 1 second
        loop (n + 1)
  loop (1 :: Int)