Descriptor.hs (1036B)
1 -- Owned raw descriptors: a failed close must never be retried against a number 2 -- the OS may already have recycled. No public descriptors or unrestricted FFI. 3 module IO.Descriptor (closeOnce, releaseOnce, duplicateSync) where 4 5 import Control.Exception (bracketOnError, mask_) 6 import Control.Monad (when) 7 import Data.IORef 8 import GHC.IO.Handle (hDuplicate) 9 import System.IO (Handle, hClose) 10 import System.Posix.IO (closeFd, handleToFd) 11 import System.Posix.Types (Fd) 12 import System.Posix.Unistd (fileSynchronise) 13 14 closeOnce :: Fd -> IO (IO ()) 15 closeOnce fd = releaseOnce (closeFd fd) 16 17 -- Injectable action for close-failure/cancellation controls. 18 releaseOnce :: IO () -> IO (IO ()) 19 releaseOnce action = do 20 owned <- newIORef True 21 pure $ mask_ $ do 22 close <- atomicModifyIORef' owned (\old -> (False,old)) 23 when close action 24 25 duplicateSync :: Handle -> IO (IO (), IO ()) 26 duplicateSync handle = mask_ $ do 27 fd <- bracketOnError (hDuplicate handle) hClose handleToFd 28 release <- closeOnce fd 29 pure (fileSynchronise fd, release)