Race condition in setNumCapabilities
|Reported by:||akio||Owned by:||simonmar|
|Operating System:||Unknown/Multiple||Architecture:||x86_64 (amd64)|
|Type of failure:||Runtime crash||Test Case:|
|Related Tickets:||Differential Rev(s):|
In HEAD, the following program sometimes deadlocks (about 1/10 of the time).
import Control.Concurrent import Control.Monad import GHC.Conc main = do mainTid <- myThreadId labelThread mainTid "main" forM_ [0..0] $ \i -> forkIO $ do subTid <- myThreadId labelThread subTid $ "sub " ++ show i forM_ [0..100000000] $ \j -> putStrLn $ "sub " ++ show i ++ ": " ++ show j yield setNumCapabilities 2
The problem seems to be that there is a race condition between setNumCapabilites and a Task returning from a foreign call. Specifically, a sequence of events like the following can happen:
- Task 0 makes a foreign call.
- Task 1 calls setNumCapabilities()
- The call on task 0 returns; it reads task->cap from the memory.
- Task 1 moves the Capabilities, invalidating all pointers to them.
- Task 0 takes over the invalidated Capability.
The attached patch adds an ASSERT to the RTS to demonstrate the problem (it does not fix the problem).