Description
Consider the following example:
import Control.Exception
import Control.Concurrent
import Control.Concurrent.Async
main = uninterruptibleMask_ (withAsync (threadDelay maxBound) (const $ return ()))
This program hangs forever.
As documentation states, withAsync
behaves like withAsync action inner = bracket (async action) uninterruptibleCancel inner
. In this case uninterruptibleCancel
hangs because the thread which it's trying to kill has MaskedUninterruptible
masking state.
I am not sure if it's supposed to work this way. Maybe it's a bug.
Note that it has the same effect for race_
and concurrently_
functions. Both examples below hang:
main = uninterruptibleMask_ (race_ (threadDelay maxBound) (return ()))
main = uninterruptibleMask_ (concurrently_ (threadDelay maxBound) (error "foo"))
There is a simple workaround for it:
main = uninterruptibleMask_ (withAsyncWithUnmask (\unmask -> unmask $ threadDelay maxBound) (const $ return ()))
This program doesn't hang. Shouldn't it be the default behaviour? I. e. shouldn't withAsync
change masking state of spawned thread automatically?