import Control.Exception as E
import Control.Concurrent
import System.IO.Unsafe

-- x is killed during evaluation with an asynchronous exception, but
-- nevertheless gets overwritten with 'throw ThreadKilled' because the
-- async exception is re-thrown as a synchrnonous exception by
-- 'onException'.

main = do
  let x = unsafePerformIO $ 
             (do threadDelay 1000000; return 42)
             `onException` return ()

  t <- forkIO $ do evaluate x; return ()
  threadDelay 1000
  killThread t

  print x `E.catch` \e -> putStrLn ("main caught: " ++ show (e::SomeException))
