content: import Control.Concurrent
  import Control.Exception
  
  -- check that async exceptions are restored to their previous
  -- state after an exception is raised and handled.
  
  main = do
    main_thread <- myThreadId
    m1 <- newEmptyMVar
    m2 <- newEmptyMVar
    m3 <- newEmptyMVar
    forkIO (do 
  	     takeMVar m1
  	     throwTo main_thread (ErrorCall "foo")
  	     takeMVar m2
  	     throwTo main_thread (ErrorCall "bar")
  	     putMVar m3 ()
  	 )
    (do 
      mask $ \restore -> do
  	(do putMVar m1 () 
  	    restore (
  		-- unblocked, "foo" delivered to "caught1"
  	       myDelay 100000
  	     )
  	 ) `Control.Exception.catch` 
                \e -> putStrLn ("caught1: " ++ show (e::SomeException))
  	putMVar m2 ()
  	-- blocked here, "bar" can't be delivered
  	(sum [1..10000] `seq` return ())
  	  `Control.Exception.catch` 
                \e -> putStrLn ("caught2: " ++ show (e::SomeException))
      -- unblocked here, "bar" delivered to "caught3"
      takeMVar m3
     )
     `Control.Exception.catch` 
         \e -> putStrLn ("caught3: " ++ show (e::SomeException))
  
  -- compensate for the fact that threadDelay is non-interruptible
  -- on Windows with the threaded RTS in 6.6.
  myDelay usec = do
    m <- newEmptyMVar
    forkIO $ do threadDelay usec; putMVar m ()
    takeMVar m
  