title: How to catch async exceptions with the safe-exceptions library?
body: <p>I'm trying to dive into building concurrent and robust code with Haskell, and it was recommended that I use the <a href="https://hackage.haskell.org/package/safe-exceptions" rel="nofollow noreferrer">safe-exceptions</a> and <a href="https://hackage.haskell.org/package/async" rel="nofollow noreferrer">async</a> libraries. However, I'm having a hard time understanding how to handle non-fatal errors thrown within an <code>async</code> action. </p>
  
  <p>For instance, if there is a simple loop that is checking a network resource every <em>n</em> seconds, it would make sense to stop this using the <code>cancel</code> function which would cause an <code>AsyncCancelled</code> exception to be thrown within the seperate thread. Of course, there would also be the possibility that an <code>IOError</code> would be thrown from within the thread due to the network going down or some other problem. Depending on the type of exception and the data it contains, I would want to control whether the seperate thread ignores the exception, performs some action, stops, or raises the exception in the main thread.</p>
  
  <p>With the safe-exceptions library, the only functions that are able to do this are <code>catchAsync</code> and others like it, which are labelled as dangerous in the documentation. Other than that, there is <code>waitCatch</code> in the async library, but the <code>fromException</code> function always returns <code>Nothing</code> when I try to extract an <code>IOError</code>:</p>
  
  <pre><code>{-# LANGUAGE ScopedTypeVariables #-}
  
  import Control.Concurrent.Async
  import Control.Concurrent hiding (throwTo)
  import Control.Exception.Safe 
  import Control.Monad
  import System.IO
  import System.IO.Error hiding (catchIOError)
  
  main = do
      hSetBuffering stdin NoBuffering
      putStrLn "Press any key to continue..."
      a &lt;- async runLoop
      async $ hWaitForInput stdin (-1) *&gt; 
                  throwTo (asyncThreadId a) (userError "error")
      waitCatch a &gt;&gt;= either handler nothing
    where
      printThenWait i = putStr (show i ++ " ") *&gt; threadDelay 1000000
      runLoop = sequence_ $ printThenWait &lt;$&gt; [1..]
      nothing _ = pure ()
      handler e
          | Just (e' :: IOError)       &lt;- fromException e = 
                putStrLn "It's an IOError!"
          | (Nothing :: Maybe IOError) &lt;- fromException e = 
                putStrLn "We got Nothing!"
  </code></pre>
  
  <p>I'm a bit confused about the danger of recovering from async exceptions, especially when standard functions such as <code>cancel</code> cause them to be thrown, and I don't know what the recommended way to handle them would be when using these two libraries. Is this an instance where <code>catchAsync</code> <em>would</em> be recommended, or is there another way to handle these types of situations that I haven't discovered?</p>