【发布时间】:2011-10-30 05:34:36
【问题描述】:
我正在为 Haskell 中的 Scheme 解释器实现 REPL,我想处理一些异步事件,如 UserInterrupt、StackOverflow、HeapOverflow 等...基本上,我想在 UserInterrupt 发生时停止当前计算并在发生 StackOverflow 和 HeapOverflow 等时打印合适的消息。我实现如下:
repl evaluator = forever $ (do
putStr ">>> " >> hFlush stdout
out <- getLine >>= evaluator
if null out
then return ()
else putStrLn out)
`catch`
onUserInterrupt
onUserInterrupt UserInterrupt = putStrLn "\nUserInterruption"
onUserInterrupt e = throw e
main = do
interpreter <- getMyLispInterpreter
handle onAbort (repl $ interpreter "stdin")
putStrLn "Exiting..."
onAbort e = do
let x = show (e :: SomeException)
putStrLn $ "\nAborted: " ++ x
它按预期工作,但有一个例外。如果我启动解释器并按 Ctrl-Z + Enter,我会得到:
>>> ^Z
Aborted: <stdin>: hGetLine: end of file
Exiting...
没错。但是如果我启动解释器并按 Ctrl-C 然后按 Ctrl-Z + Enter 我得到:
>>>
UserInterruption
>>> ^Z
它挂了,我不能再使用解释器了。但是,如果我再次按 Ctrl-C,REPL 就会解除阻塞。我搜索了很多,我无法弄清楚它的原因。谁能解释一下?
非常感谢!
【问题讨论】:
-
我从未见过 Ctrl-Z 被抓到。第一个 Ctrl-C 被捕获,但第二个没有。这大概是同一个问题。你能在一个完整的工作测试用例中改变你的代码吗? F.e. 'return' 而不是 'interpreter "stdin"' 并添加了正确的导入。
标签: exception haskell exception-handling read-eval-print-loop interruption