Bug in IO libraries when sending data through a pipe?

Volker Wysk post@volker-wysk.de
20 Mar 2002 22:08:51 +0100

On Mit, 2002-03-20 at 07:00, Jens Petersen wrote:
> Jens Petersen <petersen@redhat.com> writes:
> > > The problem is that the child process doesn't receive all the data which
> > > the parent sends. It's as if "hPutStr vonh txt" sends the data lazily
> > > somehow, and "hClose vonh" closes the pipe prematurely.
> > > 
> > > It varies from run to run exactly which data gets through. If I cause the
> > > child process to read all its input immediately, the problem doesn't
> > > seem to occur. Normally, it does so gradually, which takes a few seconds.
> > > 
> > > I'm using GHC 5.02.2
> > 
> > Quite possibly could be a bug.  Lazy IO is rather subtle I
> > think, specially when done across pipes.  I faced some
> > similar problem with in POpen recently.  You can see how I
> > solved it (worked round it?) by comparing the latest release
> > 1.00 with the previous one 0.00.1:
> > 
> >         http://www.01.246.ne.jp/~juhp/haskell/popenhs/

POpen-1.0.0 contains the same bug which I made. It doesn't ensure that
the values which are needed after the call of forkProcess, before that
of executeFile, are fully evaluated. So, if they are read lazily from a
stream, the newly spawned child process reads data from a stream which
it shares with its parent, making it disappear from the parent's input.
In this situation, this sure isn't intended.

Inserting the following lines just before the line "pid <- forkProcess",
in POpen.hs, would force the corresponding values to be evaluated, so no
data will be lost.

    seq (length path) $ seq (sum (map length args)) $ return ()
    when (isJust env) $ seq (sum (map (\(a,b) -> length a + length b) 
                                      (fromJust env))) $ return ()
    when (isJust dir) $ seq (length (fromJust dir)) $ return ()

I'm also not sure what this part is supposed to do:

    inr <- if (isJust inpt) then
	     (inr', inw) <- createPipe
	     hin <- fdToHandle inw
	     hPutStr hin $ fromJust inpt
	     hClose hin
	     return $ Just inr'
	    return Nothing

Doesn't it write the input data to a pipe which no process reads