@@ -41,16 +41,19 @@ import Network.Transport
4141import System.Random (randomIO)
4242import System.IO (IOMode(ReadMode,AppendMode,WriteMode,ReadWriteMode),
4343 openFile, hClose, hPutStrLn, hPutStr, stderr, stdout, hFlush)
44+import System.IO.Error (ioeGetHandle)
4445import System.Posix.Files (createNamedPipe, unionFileModes, ownerReadMode, ownerWriteMode)
4546import System.Posix.Types (Fd)
4647import System.Directory (doesFileExist, removeFile)
48+import System.Mem (performGC)
4749
4850-- define DEBUG
4951-- define USE_UNIX_BYTESTRING
5052
5153#ifdef USE_UNIX_BYTESTRING
5254import qualified "unix-bytestring" System.Posix.IO.ByteString as PIO
53−import System.Posix.IO as PIO (openFd, defaultFileFlags, OpenMode(ReadWrite, WriteOnly))
55+import System.Posix.IO as PIO (openFd, closeFd, defaultFileFlags,
56+ OpenMode(ReadWrite, WriteOnly))
5457(fromS,toS) = (BS.pack, BS.unpack)
5558(fromBS,toBS) = (id,id)
5659readit fd n = PIO.fdRead fd n
@@ -91,8 +94,14 @@ mkTransport = do
9194
9295 return Transport
9396 { newConnectionWith = \ _ -> do
97+ -- Here we protect from blocking other threads by running on a separate (OS) thread:
98+ -- Opening the file on the reader side should always succeed:
99+ mv <- onOSThread$ tryUntilNoIOErr $
100+-- spinTillThere filename
101+ PIO.openFd filename PIO.ReadOnly Nothing fileFlags
102+
94103 return (mkSourceAddr filename,
95− mkTargetEnd filename lock)
104+ mkTargetEnd mv lock)
96105 , newMulticastWith = error "Pipes.hs: newMulticastWith not implemented yet"
97106 , deserialize = \bs -> return$ mkSourceAddr (BS.unpack bs)
98107 , closeTransport = removeFile filename
@@ -107,11 +116,9 @@ mkTransport = do
107116 mkSourceEnd :: String -> IO SourceEnd
108117 mkSourceEnd filename = do
109118 -- Initiate but do not block on file opening:
110−
111− -- Here we protect from blocking other threads by running on a separate (OS) thread:
112119 mv <- onOSThread$ tryUntilNoIOErr $
113120 -- The reader must connect first, the writer here spins with backoff.
114− PIO.openFd filename PIO.WriteOnly Nothing fileFlags
121+ PIO.openFd filename PIO.WriteOnly Nothing fileFlags
115122
116123 return $
117124 -- Write to the named pipe. If the message is less than
@@ -128,31 +135,26 @@ mkTransport = do
128135-- let finalmsg = BS.concat (encode msgsize : bss)
129136 let finalmsg = BS.concat ((BS.fromChunks[encode msgsize]) : bss)
130137
131− fd <- readMVar mv -- Synchronnize with file opening.
138+ fd <- readMVar mv -- Synchronize with file opening.
132139 ----------------------------------------
133140 cnt <- PIO.fdWrite fd (fromBS finalmsg) -- inefficient to use String here!
134141 unless (fromIntegral cnt == BS.length finalmsg) $
135142 error$ "Failed to write message in one go, length: "++ show (BS.length finalmsg)
136143 ----------------------------------------
137144 return ()
138− , closeSourceEnd = error "Pipes.hs: closeSourceEnd not yet implemented"
145+ , closeSourceEnd = do
146+ fd <- readMVar mv
147+ PIO.closeFd fd
139148 }
140149
141− mkTargetEnd :: String -> MVar () -> TargetEnd
142− mkTargetEnd filename lock = TargetEnd
150+ mkTargetEnd :: MVar Fd -> MVar () -> TargetEnd
151+ mkTargetEnd mv lock = TargetEnd
143152 { receive = do
153+ fd <- readMVar mv -- Make sure Fd is there before
154+
144155 -- This should only happen on a single process. But it may
145156 -- happen on multiple threads so we grab a lock.
146157 takeMVar lock
147−
148− spinTillThere filename
149− -- Opening the file on the reader side should always succeed:
150− fd <- PIO.openFd filename PIO.ReadOnly Nothing fileFlags
151−
152− let oneread fd n =
153− do bs <- tryUntilNoIOErr$
154− readit fd (fromIntegral n)
155− return (bs, BS.length bs)
156158
157159 let spinread :: Int64 -> IO BS.ByteString
158160 spinread desired = do
@@ -178,7 +180,9 @@ mkTransport = do
178180 Right size -> spinread (fromIntegral (size::Word32))
179181 putMVar lock ()
180182 return [payload]
181− , closeTargetEnd = error "Pipes.hs: closeTargetEnd not yet implemented"
183+ , closeTargetEnd = do
184+ fd <- readMVar mv
185+ PIO.closeFd fd
182186 }
183187
184188spinTillThere :: String -> IO ()
@@ -202,6 +206,10 @@ tryUntilNoIOErr action = mkBackoff >>= loop
202206 loop bkoff =
203207 handle (\ (e :: IOException) ->
204208 do bkoff
209+-- BSS.hPutStr stderr$ BSS.pack$ " got IO err: " ++ show e
210+ -- case ioeGetHandle e of
211+ -- Nothing -> BSS.hPutStrLn stderr$ BSS.pack$ " no hndl io err."
212+ -- Just x -> BSS.hPutStrLn stderr$ BSS.pack$ " HNDL on io err!" ++ show x
205213 loop bkoff) $
206214 action
207215