@@ -41,16 +41,19 @@ import Network.Transport
41import System.Random (randomIO)
41import System.Random (randomIO)
42import System.IO (IOMode(ReadMode,AppendMode,WriteMode,ReadWriteMode),
42import System.IO (IOMode(ReadMode,AppendMode,WriteMode,ReadWriteMode),
43 openFile, hClose, hPutStrLn, hPutStr, stderr, stdout, hFlush)
43 openFile, hClose, hPutStrLn, hPutStr, stderr, stdout, hFlush)
44+import System.IO.Error (ioeGetHandle)
44import System.Posix.Files (createNamedPipe, unionFileModes, ownerReadMode, ownerWriteMode)
45import System.Posix.Files (createNamedPipe, unionFileModes, ownerReadMode, ownerWriteMode)
45import System.Posix.Types (Fd)
46import System.Posix.Types (Fd)
46import System.Directory (doesFileExist, removeFile)
47import System.Directory (doesFileExist, removeFile)
48+import System.Mem (performGC)
48-- define DEBUG
50-- define DEBUG
49-- define USE_UNIX_BYTESTRING
51-- define USE_UNIX_BYTESTRING
51#ifdef USE_UNIX_BYTESTRING
53#ifdef USE_UNIX_BYTESTRING
52import qualified "unix-bytestring" System.Posix.IO.ByteString as PIO
54import 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))
54(fromS,toS) = (BS.pack, BS.unpack)
57(fromS,toS) = (BS.pack, BS.unpack)
55(fromBS,toBS) = (id,id)
58(fromBS,toBS) = (id,id)
56readit fd n = PIO.fdRead fd n
59readit fd n = PIO.fdRead fd n
@@ -91,8 +94,14 @@ mkTransport = do
92 return Transport
95 return Transport
93 { newConnectionWith = \ _ -> do
96 { 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
94 return (mkSourceAddr filename,
103 return (mkSourceAddr filename,
95− mkTargetEnd filename lock)
104+ mkTargetEnd mv lock)
96 , newMulticastWith = error "Pipes.hs: newMulticastWith not implemented yet"
105 , newMulticastWith = error "Pipes.hs: newMulticastWith not implemented yet"
97 , deserialize = \bs -> return$ mkSourceAddr (BS.unpack bs)
106 , deserialize = \bs -> return$ mkSourceAddr (BS.unpack bs)
98 , closeTransport = removeFile filename
107 , closeTransport = removeFile filename
@@ -107,11 +116,9 @@ mkTransport = do
107 mkSourceEnd :: String -> IO SourceEnd
116 mkSourceEnd :: String -> IO SourceEnd
108 mkSourceEnd filename = do
117 mkSourceEnd filename = do
109 -- Initiate but do not block on file opening:
118 -- Initiate but do not block on file opening:
111− -- Here we protect from blocking other threads by running on a separate (OS) thread:
112 mv <- onOSThread$ tryUntilNoIOErr $
119 mv <- onOSThread$ tryUntilNoIOErr $
113 -- The reader must connect first, the writer here spins with backoff.
120 -- 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
116 return $
123 return $
117 -- Write to the named pipe. If the message is less than
124 -- Write to the named pipe. If the message is less than
@@ -128,31 +135,26 @@ mkTransport = do
128-- let finalmsg = BS.concat (encode msgsize : bss)
135-- let finalmsg = BS.concat (encode msgsize : bss)
129 let finalmsg = BS.concat ((BS.fromChunks[encode msgsize]) : bss)
136 let finalmsg = BS.concat ((BS.fromChunks[encode msgsize]) : bss)
131− fd <- readMVar mv -- Synchronnize with file opening.
138+ fd <- readMVar mv -- Synchronize with file opening.
132 ----------------------------------------
139 ----------------------------------------
133 cnt <- PIO.fdWrite fd (fromBS finalmsg) -- inefficient to use String here!
140 cnt <- PIO.fdWrite fd (fromBS finalmsg) -- inefficient to use String here!
134 unless (fromIntegral cnt == BS.length finalmsg) $
141 unless (fromIntegral cnt == BS.length finalmsg) $
135 error$ "Failed to write message in one go, length: "++ show (BS.length finalmsg)
142 error$ "Failed to write message in one go, length: "++ show (BS.length finalmsg)
136 ----------------------------------------
143 ----------------------------------------
137 return ()
144 return ()
138− , closeSourceEnd = error "Pipes.hs: closeSourceEnd not yet implemented"
145+ , closeSourceEnd = do
141− mkTargetEnd :: String -> MVar () -> TargetEnd
150+ mkTargetEnd :: MVar Fd -> MVar () -> TargetEnd
142− mkTargetEnd filename lock = TargetEnd
151+ mkTargetEnd mv lock = TargetEnd
143 { receive = do
152 { receive = do
153+ fd <- readMVar mv -- Make sure Fd is there before
144 -- This should only happen on a single process. But it may
155 -- This should only happen on a single process. But it may
145 -- happen on multiple threads so we grab a lock.
156 -- happen on multiple threads so we grab a lock.
146 takeMVar lock
157 takeMVar lock
148− spinTillThere filename
149− -- Opening the file on the reader side should always succeed:
150− fd <- PIO.openFd filename PIO.ReadOnly Nothing fileFlags
153− do bs <- tryUntilNoIOErr$
154− readit fd (fromIntegral n)
155− return (bs, BS.length bs)
157 let spinread :: Int64 -> IO BS.ByteString
159 let spinread :: Int64 -> IO BS.ByteString
158 spinread desired = do
160 spinread desired = do
@@ -178,7 +180,9 @@ mkTransport = do
178 Right size -> spinread (fromIntegral (size::Word32))
180 Right size -> spinread (fromIntegral (size::Word32))
179 putMVar lock ()
181 putMVar lock ()
180 return [payload]
182 return [payload]
181− , closeTargetEnd = error "Pipes.hs: closeTargetEnd not yet implemented"
183+ , closeTargetEnd = do
184spinTillThere :: String -> IO ()
188spinTillThere :: String -> IO ()
@@ -202,6 +206,10 @@ tryUntilNoIOErr action = mkBackoff >>= loop
202 loop bkoff =
206 loop bkoff =
203 handle (\ (e :: IOException) ->
207 handle (\ (e :: IOException) ->
204 do bkoff
208 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
205 loop bkoff) $
213 loop bkoff) $