GHC API: Using runGhc twice or from multiple threads?

Hello, is the following safe to do? main = do runGhc libdir $ do ... runGhc libdir $ do ... Or will this cause trouble? Is there state that is shared between the two calls? And what about this one: main = do forkIO $ runGhc libdir $ do ... forkIO $ runGhc libdir $ do ...

Benno I think that both ought to be ok, but I'd welcome other input. GHC.runGHC calls initGhcMonad, which allocates an entirely new session (in newHscEnv). So the two will work entirely independently. Unfortunately that's not 100% true. If you search for GLOBAL_VAR you'll see a handful of disgusting global state variables, and they *will* be shared between GHC sessions. There really aren't many. I'd love someone to eliminate them! (NB ghc-devs) Simon From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Benno Fünfstück Sent: 07 January 2014 13:56 To: ghc-devs Subject: GHC API: Using runGhc twice or from multiple threads? Hello, is the following safe to do? main = do runGhc libdir $ do ... runGhc libdir $ do ... Or will this cause trouble? Is there state that is shared between the two calls? And what about this one: main = do forkIO $ runGhc libdir $ do ... forkIO $ runGhc libdir $ do ...

On 07/01/2014 13:55, Benno Fünfstück wrote:
Hello,
is the following safe to do?
main = do runGhc libdir $ do ... runGhc libdir $ do ...
Or will this cause trouble? Is there state that is shared between the two calls?
The main restriction here is that you can only set the static flags once, because they depend on some global mutable state (the GLOBAL_VARs that Simon mentioned).
And what about this one:
main = do forkIO $ runGhc libdir $ do ... forkIO $ runGhc libdir $ do ...
The problem with this is the RTS linker, which is a single piece of shared global state. We could actually fix that if it became important. If you're not running interpreted code, this should be fine (apart from the static flags issue mentioned above). Cheers, Simon

Simon Marlow
And what about this one:
main = do forkIO $ runGhc libdir $ do ... forkIO $ runGhc libdir $ do ...
The problem with this is the RTS linker, which is a single piece of shared global state. We could actually fix that if it became important. If you’re not running interpreted code, this should be fine (apart from the static flags issue mentioned above).
I’m curious, what is the issue with interpreted code? Does the interpreter store interpreter state in the RTS, which would get mixed up between the two instances? If so, wouldn’t the same thing happen if I use forkIO in interpreted code? Manuel

On 24/01/14 01:38, Manuel M T Chakravarty wrote:
Simon Marlow
: And what about this one:
main = do forkIO $ runGhc libdir $ do ... forkIO $ runGhc libdir $ do ...
The problem with this is the RTS linker, which is a single piece of shared global state. We could actually fix that if it became important. If you’re not running interpreted code, this should be fine (apart from the static flags issue mentioned above).
I’m curious, what is the issue with interpreted code? Does the interpreter store interpreter state in the RTS, which would get mixed up between the two instances?
If so, wouldn’t the same thing happen if I use forkIO in interpreted code?
It is the linker state that is shared, that is, the mapping from symbol names to object code addresses. So you can certainly do concurrency in an interpreted program, but you can't load two different sets of object files into two instances of GHC running in separate threads. This is true regardless of whether we're using the system linker or the RTS linker. In the RTS linker case it's fixable easily enough, in the system linker case there's really only one global symbol table (populated by RTLD_GLOBAL) so I'm not sure whether there's a way around that. Cheers, Simon

I should have thought of that. Thanks for the clarification.
Cheers,
Manuel
Simon Marlow
On 24/01/14 01:38, Manuel M T Chakravarty wrote:
Simon Marlow
: And what about this one:
main = do forkIO $ runGhc libdir $ do ... forkIO $ runGhc libdir $ do ...
The problem with this is the RTS linker, which is a single piece of shared global state. We could actually fix that if it became important. If you’re not running interpreted code, this should be fine (apart from the static flags issue mentioned above).
I’m curious, what is the issue with interpreted code? Does the interpreter store interpreter state in the RTS, which would get mixed up between the two instances?
If so, wouldn’t the same thing happen if I use forkIO in interpreted code?
It is the linker state that is shared, that is, the mapping from symbol names to object code addresses. So you can certainly do concurrency in an interpreted program, but you can't load two different sets of object files into two instances of GHC running in separate threads. This is true regardless of whether we're using the system linker or the RTS linker. In the RTS linker case it's fixable easily enough, in the system linker case there's really only one global symbol table (populated by RTLD_GLOBAL) so I'm not sure whether there's a way around that.
Cheers, Simon
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs
participants (4)
-
Benno Fünfstück
-
Manuel M T Chakravarty
-
Simon Marlow
-
Simon Peyton Jones