Why it's dangerous to fork off a new process in Glasgow Haskell

George Russell ger@tzi.de
Wed, 04 Sep 2002 12:52:03 +0200


Volker Stolz wrote (about GHC.Conc.forkProcess):
[snip]
> > Interesting.  How exactly does it work, by the way?
> 
> Trade secret ;) Simply drop the TSO pointers to all other threads
> from the queues so the RTS won't find them again (GC is a
> different issue).
Ah I see.  The code is in ghc/rts/Schedule.c, in the function forkProcess.
> 
> > Posix.runProcess really should use it I think.
> 
> No, it's better to be able to choose the way to handle this.
> Maybe add a flag to Posix.runProcess. But the whole
> GHC.Conc.forkProcess isn't finished, yet, anyway.
I don't really see the point of allowing the user to choose the old way.
Posix.runProcess is supposed to fork off a new process outside of this
runtime system.  I don't see any way this can be helped by allowing other
threads to continue in the child until the actual time of exec, unless for
some reason the evaluation of the arguments to exec somehow relies on other
threads.  But this would surely at least require argument evaluation to 
unsafely conceal IO, and in any case could be better fixed by forcing the
arguments to be fully evaluated before the fork.
> 
> > The signature of Posix.runProcess is not quite adequate though; one wants some control
> > over the child thread.  At a minimum, it would be nice to be able to kill it.
>                 ^^^^^^^^
>                  process?
> 
> You still get the child's pid, so feel free to mess with it.
You don't get it from Posix.runProcess.  Posix.runProcess is supposed to be
OS-independent (even though it's only available in Posix) and I'm not sure if
a pid makes much sense on Windows anyway.

What I think I would like on all systems is a new abstract data type ChildProcess
with functions

runProcess :: FilePath -> [String] -> Maybe [(String,String)] -> Maybe FilePath ->
   Maybe Handle -> Maybe Handle -> Maybe Handle -> IO ChildProcess

(so the same as Posix.runProcess now except for returning ChildProcess)

and

killChildProcess :: ChildProcess -> IO ()

and ideally something like Posix.getProcessStatus as well.

This is not completely trivial to implement; for example one would like runProcess
to raise some exception if the exec fails, which means passing the information
back to the parent in some way.  But if you put together Sigbjorn's stuff for Windows
and the existing Posix code it shouldn't be too hard.