
I'm just tried writing a function to allow convenient embedding of shell commands, but I'm running into behavior I don't really understand somewhere at the intersection of lazy evaluation, IO, and threading. The function in question is: sh :: String -> String -> IO String sh cmd = \input -> do (stdin, stdout, _, pid) <- runInteractiveCommand cmd forkIO $ hPutStr stdin input >> hClose stdin -- get exit status to prevent zombie accumulation forkIO $ waitForProcess pid >> return () hGetContents stdout Simple uses like this work (prints "hi" and returns): return "hi" >>= sh "cat" >>= putStrLen However, this blocks: return "hi" >>= sh "cat" >>= sh "cat" >>= putStrLen this prints "hi\nblar" and returns return "hi" >>= sh "cat" >>= (\s -> putStrLn "blar" >> sh "cat" s) >>= putStrLn and this always returns but sometimes prints nothing and sometimes prints "hi\n" sh "echo hi" "there" >>= sh "cat" >>= putStrLn All these were tried with ghc 6.4.1 compiled with -threaded Just wondering if anybody has a good explanation of this range of behavior and/or a working rewrite of this function. -George