Hi Arash,

On Tue, Nov 12, 2013 at 10:44 AM, Arash Rouhani <rarash@student.chalmers.se> wrote:
I'm really curious why you want a "catchRethrow". I'm tempted to add such a primop myself since I'm working on problems with stack traces. I'm really interested in what use-case you had in mind. 

I'm working on dealing with problems with re-throwing asynchronous exceptions, especially in the context of using unsafePerformIO (see #8006 and the other tickets I reference there at the top). The catchRethrow I'm playing with is supposed to be used something like

threadCode :: IO ()
threadCode = catch (print notReallyPure) outerHandler
  where
    outerHandler :: SomeException -> IO ()
    outerHandler e = logMsg $ "Outer handler: " ++ show e

notReallyPure :: Integer
notReallyPure = unsafePerformIO $
    catchRethrow (go 10) innerHandler
  where
    go :: Integer -> IO Integer
    go 0 = return 1234
    go n = do logMsg (show n)
              threadDelay 100000
              go (n - 1)

    innerHandler :: SomeException -> IO Integer -> IO Integer
    innerHandler e rethrow = do
      logMsg $ "Inner handler: " ++ show e
      rethrow

logMsg :: String -> IO ()
logMsg str = do
  tid <- myThreadId
  putStrLn $ show tid ++ ": " ++ str

Given this main:

main :: IO ()
main = do
  a1 <- async threadCode
  a2 <- async threadCode
  threadDelay 500000
  cancel a1
  wait a2
  return ()

It should be the case that when thread a1 gets interrupted, thread a2 can continue evaluating the notReallyPure thunk without getting either an exception and without redoing any work. In other words, the output of this main should look like

ThreadId 2: 10
ThreadId 2: 9
ThreadId 2: 8
ThreadId 2: 7
ThreadId 2: 6
ThreadId 2: Inner handler: thread killed
ThreadId 2: Outer handler: thread killed
ThreadId 3: 5
ThreadId 3: 4
ThreadId 3: 3
ThreadId 3: 2
ThreadId 3: 1
1234

-E