[Haskell-cafe] Bug in runInteractiveProcess?

John Goerzen jgoerzen at complete.org
Tue Oct 16 16:48:01 EDT 2007


Hi everyone,

I have been trying to implement a Haskell-like version of shell
pipelines using runInteractiveProcess.  I am essentially using
hGetContents to grab the output from one command, and passing that to
(forkIO $ hPutStr) to write to the next.  Slow, but this is just an
experiment.  This works OK to link together two external commands, but
deadlocks when linking together three processes.

After staring at straces all afternoon, I think I have found the
culprit.

I observed that when I have three commands linked together, the second
never sees EOF on its input.  This even though I saw an explicit close
on the other end of the pipe from the Haskell side.  Why is this, I
wondered?

I stared at the source for the C runInteractiveProcess function for a
bit, but then the answer was right there: this function does not
sanitize FDs.

What that means is that the write end of the stdin pipe for command 2
was open in the Haskell process.  The Haskell process then forked off
for command 3 later on.  This write end of the stdin pipe for command 2
was never closed in the command 3 child environment.  Therefore, closing
it in the Haskell thread did not cause command 2 to get an EOF.  Does
that make sense?

Many systems will just try to close *all* FDs except the ones they need
after a fork().  Another approach would be to maintain a global list of
FDs that the Haskell thread is using, and close all of them except the
pipe ends in the child.

Without something like this, it is not possible to use
runInteractiveProcess more than twice simultaneously in a single
program.  That renders it almost useless for some tasks.

Does this make sense to everyone?  If so, I'll submit the bug on GHC.

-- John



More information about the Haskell-Cafe mailing list