VsCode中Haskell调试后ghci-dap未关闭,端口占用问题求助
调试Haskell Scotty项目时ghci-dap无法自动关闭,端口被占用且出现terminate超时警告
问题描述
我在Ubuntu 20.04上运行一个小型Haskell Scotty示例,使用VSCode + Haskell Language Server作为编辑器,Stack作为项目构建工具,GHCI版本为9.2.5。
停止调试会话时,VSCode弹出**"timeout after 2000ms for 'terminate'"**警告,且ghci-dap进程未自动关闭。强制退出调试器后,端口3000被占用导致无法重启调试,执行sudo lsof -i:3000可见ghci-dap仍在监听该端口。
示例代码:
{-# LANGUAGE OverloadedStrings #-} import Web.Scotty (scotty, post) import Control.Monad.IO.Class main :: IO () main = scotty 3000 $ do get "/" $ do liftIO $ putStrLn "helloworld"
原因分析与解决方案
1. 为什么会出现"terminate"超时警告?
VSCode调试器发送终止信号给ghci-dap后,会等待2000毫秒确认进程退出。如果ghci-dap因为内部活跃线程(比如Scotty的HTTP服务器线程)未终止而卡住,无法在超时窗口内响应终止请求,就会触发这个警告。
2. 为什么ghci-dap无法自行关闭?
Scotty的scotty函数启动的HTTP服务器是阻塞式的,会持续占用主线程运行。调试会话终止时,ghci-dap无法正确向Scotty的服务器线程发送终止信号,或者线程本身没有设置中断处理逻辑,导致线程一直处于活跃状态。ghci-dap进程因存在未退出的活跃线程,无法正常终止,进而持续占用端口3000。
解决办法
- 修改代码添加中断支持:改用
scottyApp配合Warp的可配置服务器,添加信号处理逻辑,让服务器能响应终止信号并退出:{-# LANGUAGE OverloadedStrings #-} import Web.Scotty (scottyApp, get) import Control.Monad.IO.Class import Network.Wai.Handler.Warp (runSettings, defaultSettings, setPort, setInstallShutdownHandler) import System.Posix.Signals (installHandler, sigINT, sigTERM, Handler(Catch), raiseSignal) main :: IO () main = do let port = 3000 -- 设置关闭回调,收到终止信号时触发中断 settings = setPort port $ setInstallShutdownHandler (raiseSignal sigINT) defaultSettings app <- scottyApp $ do get "/" $ do liftIO $ putStrLn "helloworld" runSettings settings app - 手动终止进程:遇到端口被占用时,直接杀掉对应的ghci-dap进程:
sudo kill -9 $(sudo lsof -t -i:3000) - 升级工具版本:GHCI 9.2.5的ghci-dap可能存在已知的进程终止bug,尝试升级到GHCI 9.4及以上版本,同时同步升级Haskell Language Server到对应兼容版本,这类问题在新版本中可能已被修复。
内容的提问来源于stack exchange,提问作者TheQuestioner
相关产品推荐
相关产品推荐

