ghci and ghc -threaded broken with pipes & forking
Simon Marlow
simonmarhaskell at gmail.com
Thu Mar 1 11:21:45 EST 2007
John Goerzen wrote:
> On Thu, Mar 01, 2007 at 03:06:22PM +0000, Simon Marlow wrote:
>> Ok, what happens here is that in the forked process there is only a single
>> thread, the runtime kills all the other threads (as advertised).
>> Unfortunately this includes the I/O manager thread, so as soon as you do
>> some I/O in the forked process, you block.
>
> Could it just revert to the nonthreaded IO model, or is that not within
> the scope of what's easily achievable with the threaded RTS?
The non-threaded I/O system just isn't compiled into the threaded RTS at all.
We used to use it in the threaded RTS before we switched to the I/O manager
thread, but as I recall it was a rich source of bugs; the I/O manager thread is
much simpler, being in Haskell.
>> On a more general note, forkProcess is known to be hairy - simply the fact
>> that it kills all the other threads in the system in the forked process
>> means that there's a good supply of means to shoot yourself in the foot,
>> even accidentally. John - perhaps there's another way to achieve what you
>> want?
>
> Right. Part of this problem may be one of documentation, and part of it
> rests with ghci.
>
> I have no need for threads in this program. And, in fact, as you said,
> threads are known to be hazardous when used in conjuntion with fork().
> I have no interest in combining the to. The mechanics of signal
> propogation, file descriptor closing, etc. all get complicated.
>
> But it seems like there is not much choice with ghci. It appears to be
> built with the threaded RTS by default, and uses threads even though I
> never try to use threads with it. And there seems to be no way to turn
> it off.
The problem is that the choice between -threaded and non-threaded is made at
link-time, so we have to make that choice when we link the GHCi binary.
In fact you should think of the non-threaded RTS as deprecated. It isn't
Haskell'-compliant, for one thing (assuming that Haskell' will probably require
non-blocking foreign calls).
I'm hesitant to actually deprecate it, for a few reasons: the threaded RTS is so
much more complicated, it might have some adverse performance impliciations, and
there are still people who want to run everything in a single OS thread, for
whatever reason. But having multiple variants of the RTS is a maintenance and
testing headache.
> Between that and the lack of support for forkProcess in Hugs, this
> renders anything that needs to fork and then do I/O as being usable only
> in GHC-compiled code. Which is sub-optimal, but livable anyway.
I guess I'm really wondering why you need to fork and do I/O at all. Can you
describe the problem at a higher level?
> Also, why does hGetContents not work, but hPutStr does? If the IO
> manager is dead, how does some IO still work?
Ah well, only I/O that needs to block uses the I/O manager thread. I/O that
doesn't block just proceeds directly.
Cheers,
Simon
More information about the Glasgow-haskell-users
mailing list