Asynchronous exception bug in spawn

Description

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:

```haskell
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:

```haskell
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.

Environment

None

Assignee

Edsko de Vries

Reporter

basvandijk

External issue ID

None

OS

None

Affects versions

Priority

Major
Configure