为何无法打印通过标准输入传入createProcess启动进程的文本?
Haskell System.Process 代码执行卡住问题解析
我在查找
System.Process的使用示例时,找到了一段代码:import System.IO import System.Process main = do (Just hin, Just hout, _, _) <- createProcess (proc "grep" ["hello"]) { std_in = CreatePipe, std_out = CreatePipe } hPutStr hin "hello grep\ngoodbye grep" grepBytes <- hGetContents hout putStrLn "> grep hello" putStrLn grepBytes程序执行会卡在最后一行,改成
putStrLn "1" >> putStrLn grepBytes >> putStrLn "2"后,只会打印出1,请问这是什么原因?
核心原因
hGetContents是懒加载的,它会一直等待输入直到遇到EOF;同时你没有关闭grep的输入管道hin,导致grep进程一直等待更多输入,不会退出,也就不会输出EOF,你的程序因此卡在等待hout内容的步骤上。
修复方案
- 写完输入后立即关闭
hin,明确告诉grep没有更多输入; - 等待grep进程结束,避免僵尸进程,同时确保输出全部读取完成。
修复后的代码示例:
import System.IO import System.Process import Control.Concurrent (waitForProcess) main = do (Just hin, Just hout, _, procHandle) <- createProcess (proc "grep" ["hello"]) { std_in = CreatePipe, std_out = CreatePipe } hPutStr hin "hello grep\ngoodbye grep" hClose hin -- 关闭输入管道,让grep终止等待输入 grepBytes <- hGetContents hout putStrLn "> grep hello" putStrLn grepBytes _ <- waitForProcess procHandle -- 等待进程退出,清理系统资源 hClose hout -- 关闭输出管道
补充说明
hClose hin是解决卡住的关键:没有这一步,grep会一直阻塞在读取stdin,永远不会输出结果,hGetContents也会一直等待EOF,导致程序卡死;waitForProcess能确保进程正常退出,避免僵尸进程,还能获取退出码用于错误处理;- 懒加载的
hGetContents在你实际使用grepBytes时才会开始读取,若输入管道未关闭,这个读取操作会无限期等待。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

