Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exceptions not being caught by 'try'

I'm using hedis and trying to handle the case of the server going dead. According to the documentation:

Connection to the server lost: In case of a lost connection, command functions throw a ConnectionLostException. It can only be caught outside of runRedis.

So I would assume I want to catch the ConnectionLostException. However, whilst I can seem to catch it correctly, it seems to also bubble up to the top, and I'm not sure why. Here's some code (just running in GHCI):

:set -XOverloadedStrings
import Database.Redis
import Control.Exception

conn <- connect defaultConnectInfo
runRedis conn $ ping

Now, if I kill the redis server between making the connection and running the command, I get the result I expect:

&langle;interactive&rangle;: ConnectionLost *** Exception: ConnectionLost

So instead I try to do the following (I added >>= evaluate in order to attempt to force evaluation of the error, but it made no difference):

let tryR = try :: IO a -> IO (Either ConnectionLostException a)
tryR . (>>= evaluate) . runRedis conn $ ping

This gives me:

Left Con: ConnectionLost nectionLost

So I'm getting the Left result as expected, but halfway through the exception is also presumably being caught and displayed by GHCI. Is this a problem with things not being evaluated?

like image 947
Impredicative Avatar asked Jan 27 '14 15:01

Impredicative


1 Answers

Like John hinted, there seems to be somthing that prints this message to stderr.

Consider this example:

{-# LANGUAGE OverloadedStrings #-}

import Control.Concurrent (threadDelay)
import Control.Exception
import Control.Monad
import Database.Redis
import System.Mem

tryR :: IO a -> IO (Either ConnectionLostException a)
tryR = try


main :: IO ()
main = do
  conn <- connect defaultConnectInfo
  loop conn
  putStrLn $ "exiting gracefully after counting up some numbers"
  performGC
  forM_ [1..10] $ \i -> do
    print i
    threadDelay 10000 -- 0.05 seconds
  where
    loop conn = do

      e <- tryR . (>>= evaluate) . runRedis conn $ ping

      case e of
        Right x  -> do print x
                       threadDelay 1000000
                       loop conn
        Left err -> do putStrLn $ "tryR caught exception: " ++ show err

It prints:

Right Pong
Right Pong  <-------------- after this I Ctrl-C the redis server
tryR caught exception: ConnectionLost
exiting gracefully after counting up some numbers
1
test: ConnectionLost
2
3
4
5
6
7
8
9
10

This looks like something in the stack is printing this test: ConnectionLost (or test.hs: ConnectionLost if you use GHCI/runghc) asynchronously.

If that's GHC, that is probably a bug, but chances are high it is done by hedis or one of its dependencies (I haven't found it in hedis itself yet).

like image 195
nh2 Avatar answered Nov 05 '22 06:11

nh2