Haskell REPL实现:多次按下CTRL-C终止问题求解
问题原因与解决方案
为什么第二次Ctrl-C会终止REPL?
GHC运行时系统内置了保护机制:当程序正在处理UserInterrupt(第一次Ctrl-C触发的异步异常)时,如果再次收到SIGINT信号(第二次Ctrl-C),运行时会直接终止程序——这是为了避免程序陷入无法手动终止的异常处理循环。
你的代码中,catch函数在执行异常处理函数handleCC时,会自动屏蔽异步异常。此时第二次Ctrl-C的信号会被GHC判定为“强制终止”请求,直接跳过你的捕获逻辑结束进程,而不会进入handleCC里的递归捕获。
修复代码
要解决这个问题,需要在handleCC中重新开启异步异常捕获,让后续的Ctrl-C能被正常处理。可以用unmask函数解除异步异常屏蔽:
import Control.Exception import System.IO repl :: IO () repl = do putStr ">> " hFlush stdout input <- getLine `catch` handleCC repl handleCC :: AsyncException -> IO String handleCC UserInterrupt = do putStr "\n>> " hFlush stdout -- 解除异步异常屏蔽,允许后续Ctrl-C被捕获 unmask $ getLine `catch` handleCC -- 其他异步异常直接抛出,不处理 handleCC e = throwIO e
修改后,无论按下多少次Ctrl-C,REPL都会重置输入行并等待新的输入,不会直接终止程序。
内容的提问来源于stack exchange,提问作者Futarimiti
相关产品推荐
相关产品推荐

