Взаимодействие с подпроцессом во время захвата stderr haskell - PullRequest
1 голос
/ 09 апреля 2020

Итак, у меня есть программа Haskell, которая взаимодействует с подпроцессом с помощью библиотеки System.Process.Typed. Я пытаюсь захватить stderr подпроцесса в течение всей продолжительности жизни подпроцесса. Текущий метод не работает, если подпроцесс завершается до того, как я доберусь до строки *. Я думаю, что для этого мне нужно использовать 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)

1 Ответ

0 голосов
/ 09 апреля 2020

Вы не указали, что именно «не работает» в вашем коде, поэтому я попытаюсь угадать. Одна потенциальная проблема, которую я сразу вижу, состоит в том, что вы возвращаете значения, которые вы читаете из файловых дескрипторов (response1, response2, err) из вашей функции. Проблема в том, что Haskell является ленивым языком, поэтому возвращаемые вами значения не на самом деле читаются из этих дескрипторов, пока они действительно не понадобятся. И к тому моменту, когда они необходимы, дочерний процесс завершается, и дескрипторы закрываются, поэтому их невозможно прочитать.

Самое простое исправление - заставить все эти строки читать перед вами: вернуться »из вашей функции. Один стандартный рецепт для этого - использовать force, за которым следует evaluate. Это заставит вашу программу на самом деле прочитать значения и запомнить их, поэтому дескрипторы могут быть закрыты.

Итак, вместо:

value <- hGetContents handle

вы должны сделать:

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