
I wished to get output of unix commands in haskell code. So i wrote: ---------------------------------------------------------------------------------- import System.IO import System.Process eval :: String -> IO String eval s = do (_,hOutput,_,hProcess) <- runInteractiveCommand s sOutput <- hGetContents hOutput waitForProcess hProcess return sOutput ---------------------------------------------------------------------------------- 'eval' works well if output of evaluated command is less than 64Kb. If not - 'eval' never ends. What may cause this problem? Is it possible to use 'runInteractiveCommand' when command's output size is longer than 64Kb? -- Best regards, Sergey Perminov

Sergey Perminov wrote:
I wished to get output of unix commands in haskell code.
So i wrote: ---------------------------------------------------------------------------------- import System.IO import System.Process
eval :: String -> IO String eval s = do (_,hOutput,_,hProcess) <- runInteractiveCommand s sOutput <- hGetContents hOutput waitForProcess hProcess return sOutput ----------------------------------------------------------------------------------
'eval' works well if output of evaluated command is less than 64Kb. If not - 'eval' never ends.
What may cause this problem?
The laziness of hGetContents does. As long as nothing needs sOutput, it will not be read, the process becomes stuck on a clogged pipe, waitForProcess does not return and therefore nobody needs sOutput. There are two ways out: you can leave the waitForProcess out and trust that it eventually terminates or you can make eval more strict:
eval :: String -> IO String eval s = do (_,hOutput,_,hProcess) <- runInteractiveCommand s sOutput <- hGetContents hOutput foldr seq (waitForProcess hProcess) sOutput return sOutput
...but you most certainly don't want to buffer large amounts of output in a String. Depending on your actual problem, there may be far better solutions, such as
eval :: String -> (String -> IO b) -> IO b eval s k = bracket (runInteractiveCommand s) (\(_,_,_,hProcess) -> waitForProcess hProcess) (\(_,output,_,_) -> hGetContents output >>= k)
You will still run into problems if the called process writes to stdout, though. -Udo -- "You live and learn. At any rate, you live." -- Marvin, the paranoid droid
participants (2)
-
Sergey Perminov
-
Udo Stenzel