Interrupting interleaved STM and resuming it produces segfault
The following program produces a segfault:
import Control.Concurrent.STM
import Control.Exception
import System.IO.Unsafe
import System.Timeout
main :: IO ()
main = do
x <- unsafeInterleaveIO $ atomically retry
_ <- timeout 1000000 $ evaluate x
evaluate x
When a thread is interrupted while evaluating interleaved IO, and that IO is blocked on an STM transaction, resuming the suspended computation produces a segfault.
This segfault happens with GHC 7.0.3, 7.2.2, and 7.4.1, on both Windows 32-bit and Linux 64-bit, with and without -threaded.
Compiling with -debug on 7.5.20120211, I get an assertion failure in rts/STM.c, line 1525:
ASSERT (trec != NO_TREC);
In general, pure computations are not always suspended by asynchronous exceptions:
import Control.Concurrent
import System.IO.Unsafe
import System.Timeout
main :: IO ()
main = do
-- Resuming interleaved takeMVar works correctly
mv <- newEmptyMVar
_ <- forkIO $ threadDelay 2000000 >> putMVar mv "Hello"
s <- unsafeInterleaveIO $ takeMVar mv
_ <- timeout 1000000 $ putStrLn s
putStrLn s
-- But resuming getLine repeats the asynchronous exception, contrary to the
-- documentation of 'throwTo'
s <- unsafeInterleaveIO getLine
_ <- timeout 1000000 $ putStrLn s
putStrLn s
Note issue #5859 (closed) when testing: unsafeInterleaveIO being INLINE causes computations to be duplicated when shared among threads. The examples above dodge this issue by keeping the work in the current thread.
Trac metadata
Trac field | Value |
---|---|
Version | 7.4.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Runtime System |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |