Eq instance for ThreadId too coarse
ThreadIds may refer to two different threads.
It seems that for
ThreadId relies on a 32 bit counter that wraps around if
forkIO is called often enough. Yet,
killThread (fortunately) does not mix up two handles that look equal according to
The behaviour is illustrated by the following program:
import Control.Concurrent import Control.Monad main :: IO () main = do t0 <- myThreadId (`mapM_` [0 :: Integer .. ]) $ \i -> do t <- forkIO $ return () when (i `mod` 500000000 == 0) $ print t when (t == t0) $ do putStrLn $ "Killing " ++ show t ++ "..." killThread t threadDelay 1000000 putStrLn $ "Killing " ++ show t0 ++ "..." killThread t0
$ ghc -O Bug.hs && ./Bug [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug ... ThreadId 2 ThreadId 500000002 ThreadId 1000000002 ThreadId 1500000002 ThreadId 2000000002 ThreadId -1794967294 ThreadId -1294967294 ThreadId -794967294 ThreadId -294967294 Killing ThreadId 1... Killing ThreadId 1... Bug: thread killed $ echo $? 1
This reveals that
t0 refer to two different threads, although
t == t0: it seems that
killThread t kills the thread just forked, whereas
killThread t0 kills the main thread.
t0 referred to the thread just forked, the program would continue to run. If both referred to the main thread, the program would already terminate at the first invocation of