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 |