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

Sigbjorn Finne sof@galois.com
Tue, 3 Sep 2002 13:19:15 -0700

Have a look at GHC.Conc.forkProcess, which Volker Stolz
contributed a while ago. Does what you want, but I think you're
actually doing the Right Thing by implementing the fork() & exec()
outside of Haskell.


----- Original Message -----
From: "George Russell" <ger@tzi.de>
To: <glasgow-haskell-users@haskell.org>
Sent: Tuesday, September 03, 2002 10:46
Subject: Why it's dangerous to fork off a new process in Glasgow Haskell

> I have some code which forks off a new process which does some
non-Haskelly stuff.  Thus it does
> the standard things, something like
> processId <- Posix.forkProcess
> case processId of
>    Just _ -> -- parent process, continue normally
>       ...
>    Nothing -> -- child process
>       do
>          ... -- rearrange plumbing of stdin/stdout/stderr
>          Posix.executeFile [blah]
> The GHC runProcess function uses a similar mechanism.
> Unfortunately this has developed an extremely irritating bug.  The problem
is that my program has
> a lot of worker threads which do things like communicating with servers,
already running programs,
> and so on. These worker threads get replicated in the child process (like
everything else) which
> means that you now have two clients communicating with the server, where
there ought to
> be one, result chaos.  (Or in this case, the entire program coming to a
halt.)  I've had this code for
> several years (I inherited it), but the problem seems to have recently got
much worse; I don't know whether
> this is because of a change in GHC's scheduling with ghc5.04, or because I
am now compiling much more
> complicated programs.
> Whatever, I simply couldn't find a way of fixing this in Haskell.  It
would be good if there were a
> way of telling GHC's RTS scheduler "Please don't run any other threads
apart from this one until
> further notice".  If so, you could do
> [block other threads]
> [do fork]
> [if parent process
>     then
>        unblock other threads
>        ...
>     else -- child process
>        rearrange plumbing and do exec
>     ]
> But there isn't.
> So in the end I resorted to writing a C function which does both the
forking and replumbing and execing.
> Since GHC doesn't run native threads while foreign C code is executing,
this fixes the problem.
> It would be nice if there were a better way . . .
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users@haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users