You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:08:30