
I cannot reproduce pretty much any claim made in this thread. Unless PIO does not mean System.IO.Posix. I run "mkfifo hello" to create a named pipe. Then I run this program to keep trying to open for writing, non-blocking (without anyone at the read end initially): import System.Posix.IO import System.Posix.Types(Fd(..)) import qualified Control.Exception as E import Control.Concurrent(threadDelay) main = do E.handle (\e -> putStrLn ("caught exception: " ++ show (e :: E.IOException))) -- you can change IOException to SomeException too (do fd <- openFd "hello" WriteOnly Nothing defaultFileFlags{nonBlock=True} case fd of Fd n -> putStrLn ("fd number " ++ show n) -- I deliberately leak fd ) threadDelay 1500000 main openFd failures are successfully caught as exceptions; it does not return an Fd that stands for -1 when it fails. (Check its source code and chase down what throwErrnoPathIfMinus1Retry means.) When it fails, it does not leak file descriptors. "lsof hello" shows nothing. To force file descriptors to be leaked and see what lsof says, I then run "cat hello" as the read end while the above program is still running, so that openFd succeeds and I have something to leak. "lsof hello" successfully shows: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME f 3725 trebla 3w FIFO 8,5 0t0 158922 hello f 3725 trebla 4w FIFO 8,5 0t0 158922 hello f 3725 trebla 5w FIFO 8,5 0t0 158922 hello f 3725 trebla 6w FIFO 8,5 0t0 158922 hello cat 3726 trebla 3r FIFO 8,5 0t0 158922 hello My point is that if "openFd ... WriteOnly" leaks anything, you should be seeing 3w, 4w, etc., emphasis on "w". But you're seeing a ton of "r"s. Your leaker is some read-end code. Ubuntu 11.04 x86 32-bit, kernel 2.6.38, GHC 6.12.3, 7.0.4, 7.2.1, 7.4.1 Lastly, the control structure loop = handle (\e -> ... loop) job is very problematic. Go to the haddock of Control.Exception, search for the string "The difference between using try and catch for recovery" to see why. You should use this: loop = do lr <- try job case lr of Left e -> ... loop Right a -> return a i.e., get out of the exception handler as soon as possible. (Thus, my use of putStrLn inside a handler is also questionable. But mine is a toy. I wouldn't do it in production code.)