network-transport
network-transport copied to clipboard
[NT-5] Asynchronous exception bug in spawn
[Imported from JIRA. Reported by basvandijk @basvandijk) as NT-5 on 2012-10-05 14:54:16]
The following code in Network.Transport.Util is unsafe with regard to asynchronous exceptions. If an asynchronous exception is thrown to the forked thread before the endpoint address is put to the addr MVar then the final takeMVar will dead-lock:
spawn :: Transport -> (EndPoint -> IO ()) -> IO EndPointAddress
spawn transport proc = doo
addr <- newEmptyMVar
forkIO $ do
Right endpoint <- newEndPoint transport
putMVar addr (address endpoint)
proc endpoint
takeMVar addr
One way to solve this is using a combination of mask and try. However a way more simple implementation is:
spawn :: Transport -> (EndPoint -> IO ()) -> IO EndPointAddress
spawn transport proc = do
Right endpoint <- newEndPoint transport
forkIO $ proc endpoint
return $ address endpoint
Since the original code has to wait for the completion for newEndPoint anyway we could just as well execute it in the main thread and only execute proc endpoint in a separate thread. No need for an MVar so no posibility of dead-lock.
However since this code is so simple I wonder if there's actually a need for this combinator. Is it used anywhere? If not, I propose to remove it.
Moved to https://github.com/haskell-distributed/distributed-process/issues/42
There is good discussion in haskell-distributed/distributed-process#42, but it's really an issue about network-transport, not distributed-process. So we should reopen the this issue and redirect the discussion in the other issue to here.
FTR I'm up for removing this function (and its module) altogether. It's not used anywhere so far as I can see.
@mboes this function is only used in tests, so we could deprecate that and change tests.
@qnikst sounds good.