While working on a Haskell project I encounter the problem, that any exception thrown to a thread via throwTo results in a Nothing when casted from the SomeException type back into my own exception type using fromException. As a demonstration, consider this code snippet:
{-# LANGUAGE LambdaCase #-}
import Control.Concurrent (threadDelay)
import UnliftIO.Async (async, asyncThreadId, waitCatch)
import UnliftIO.Exception (Exception, SomeAsyncException (..), SomeException (..),
asyncExceptionToException, catch, fromException, throwIO,
throwTo, toException)
data MyException = Type1 | Type2
deriving (Show)
instance Exception MyException
toMyException :: SomeException -> Maybe MyException
toMyException = fromException
sleepAndThrow :: (Exception e) => Int -> e -> IO ()
sleepAndThrow i e = do
threadDelay (i * 1000000)
print e
throwIO e
main :: IO ()
main = do
t1 <- async $ sleepAndThrow 1 Type1 -- Throw Type1 in 1 second
t2 <- async $ threadDelay 500000 >> throwTo (asyncThreadId t1) Type2 -- Cancel t1 in 0.5
-- seconds with Type2
waitCatch t1 >>= \case
Left e -> putStr "Exception: " >> print (toMyException e)
Right () -> error "this should not happen"
Looking at this, I would expect the following console output:
Exception: Just Type2
Whereas I get a:
Exception: Nothing
Can anyone of you please show me, what I'm doing wrong?
Thanks in advance.