【问题标题】:Interacting with a subprocess while capturing stderr haskell在捕获 stderr haskell 时与子进程交互
【发布时间】:2020-07-22 11:43:53
【问题描述】:

所以我有一个使用 System.Process.Typed 库与子进程交互的 Haskell 程序。我试图在子进程的整个生命周期内捕获子进程的标准错误。如果子进程在我到达* 行之前完成,则当前方法不起作用。我认为要做到这一点,我需要使用 STM,但我对 STM 一无所知,所以想知道是否有更简单的方法。

fun :: MyType -> IO MyOtherType
fun inparam = withProcessWait config $ \process -> do
    hPutStrLn (getStdin process) (getStr1 inparam)
    hFlush (getStdin process)
    response1 <- hGetLine (getStdout process)

    hPutStrLn (getStdin process) (getStr2 inparam)
    hFlush (getStdin process)
    response2 <- hGetLine (getStdout process)

    err <- hGetContents (getStderr process) -- this is line *
    hClose (getStdin process)

    exitCode <- timedWaitExitCode 100 process
    return $ MyOtherType response1 response2 err
  where
    config =    setStdin createPipe
              $ setStdout createPipe
              $ setStderr createPipe
              $ fromString (fp inparam)

提前谢谢你。

编辑 1:修复了 * 标签

编辑 2:当我尝试运行代码时,我得到 Exception: [..] hGetContents: illegal operation (delayed read on closed handle)

【问题讨论】:

  • 能否请您扩展一下“不起作用”?究竟发生了什么,而不是你所期望的?
  • 如果子进程在* 行之前完成,则会引发异常,因为句柄会关闭。

标签: haskell subprocess child-process stm io-monad


【解决方案1】:

你没有在你的代码中具体说明什么“不起作用”,所以我会试着猜测一下。我可以立即看到的一个潜在问题是,您正在从函数返回从文件句柄(response1response2err)读取的值。这里的问题是 Haskell 是一种惰性语言,因此在真正需要它们之前,您返回的值不会实际上从这些句柄中读取。并且在需要它们时,子进程已经退出并且句柄已关闭,因此无法读取它们。

最简单的解决方法是在从函数“返回”之前强制读取整个字符串。一种标准方法是使用force,后跟evaluate。这将使您的程序实际上读取值并记住它们,因此可以关闭句柄。

所以,而不是:

value <- hGetContents handle

你应该这样做:

value' <- hGetContents handle
value <- evaluate $ force value'

【讨论】:

  • “你强制阅读后它可能会写一些东西”。我不这么认为。 hGetContents 读取到 EOF。如果进程刚刚停止写入,它将阻塞并等待它再次启动。在进程退出(或关闭 FD)之前,它不会返回最终的 []
  • @JosephSible-ReinstateMonica 哦,是的,我认为你是对的!那我就编辑一下。
猜你喜欢
  • 2021-03-20
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 2013-03-01
  • 2012-10-04
  • 1970-01-01
  • 2022-01-18
  • 2019-10-16
相关资源
最近更新 更多