“尝试”没有抓住例外情况

时间:2014-01-27 15:17:34

标签: exception haskell

我正在使用hedis并尝试处理服务器崩溃的情况。根据文件:

  

与服务器的连接丢失:   如果连接丢失,命令函数将抛出ConnectionLostException。它只能在runRedis之外捕获。

所以我假设我想要捕获ConnectionLostException。然而,虽然我似乎能正确地抓住它,但它似乎也冒出了顶峰,我不知道为什么。这里有一些代码(只是在GHCI中运行):

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

conn <- connect defaultConnectInfo
runRedis conn $ ping

现在,如果我在建立连接和运行命令之间杀死redis服务器,我会得到我期望的结果:

  

⟨interactive⟩:ConnectionLost   ***例外:ConnectionLost

所以我尝试执行以下操作(我添加>>= evaluate以尝试强制评估错误,但没有区别):

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

这给了我:

  

左Con:ConnectionLost   nectionLost

所以我按预期获得Left结果,但是异常的中途也可能被GHCI捕获并显示。对于没有评估的事情,这是一个问题吗?

1 个答案:

答案 0 :(得分:1)

就像约翰暗示的那样,似乎有一些东西会将此消息打印到stderr

考虑这个例子:

{-# 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

打印:

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

这看起来堆栈中的某些内容正在打印此test: ConnectionLost(如果您使用GHCI / runghc,则为test.hs: ConnectionLost 异步

如果那是GHC,那可能是一个错误,但机会很高,它由hedis或其中一个依赖项完成(我还没有在hedis中找到它)。