'try'语句未捕获异常

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

与服务器的连接丢失: 在连接丢失的情况下,命令函数会抛出ConnectionLostException异常。它只能在runRedis之外被捕获。

因此,我认为我想要捕获ConnectionLostException异常。然而,虽然我似乎可以正确地捕获它,但它似乎也会冒泡到顶部,我不知道为什么。这里是一些代码(只是在GHCI中运行):
:set -XOverloadedStrings
import Database.Redis
import Control.Exception

conn <- connect defaultConnectInfo
runRedis conn $ ping

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

⟨interactive⟩: ConnectionLost *** Exception: ConnectionLost

所以我尝试做以下操作(我添加了 >>= evaluate 以尝试强制评估错误,但没有任何区别):
let tryR = try :: IO a -> IO (Either ConnectionLostException a)
tryR . (>>= evaluate) . runRedis conn $ ping

这给了我:

左侧 Con: 连接丢失 nectionLost

所以我得到了预期的 Left 结果,但在异常处理程序运行到一半时,GHCI 也可能会捕获并显示异常。这是因为有些东西没有被评估吗?

3
我不理解。在我看来,一切都正常工作:您已将异常转换为易于检查的“Either”值。您本来希望发生什么事情? - Daniel Wagner
1
在我看来,redis包除了抛出异常外,似乎还打印了一个关于连接丢失的字符串。 - John L
@DanielWagner 我正在转换异常,但是(据我所知)仍然看到GHCI将其处理为仍在抛出。除非像JohnL说的那样,redis本身正在打印消息。 - Impredicative
你可以通过检查进程的结束状态来确定异常是否仍在抛出或只是被打印。我认为出于这个原因,你需要编译你的测试而不是在GHCI中运行它。 - Kritzefitz
1个回答

2

像约翰暗示的那样,似乎有些东西会将此消息打印到 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,那么可能是一个bug,但很有可能是由hedis或其依赖项之一完成的(我还没有在hedis本身中找到它)。

另外,请考虑为hedis打开一个问题,以澄清它是hedis还是其依赖项之一。 - nh2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接