[Haskell-cafe] Trouble with simple embedding of shell in haskell

George Brewster g at brewster.org
Wed Sep 20 23:44:22 EDT 2006

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.


More information about the Haskell-Cafe mailing list