我正在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
我的Python解释器挂起了,我无法再使用它了。但是,如果我再次按下Ctrl-C,REPL将解除阻塞。我已经搜索了很多,但找不到原因。有人能解释一下吗?
非常感谢!