Dynamic loading problem
simonmar at microsoft.com
Wed May 5 16:15:21 EDT 2004
On 30 April 2004 18:01, Duncan Coutts wrote:
> On Fri, 2004-04-30 at 17:36, Simon Marlow wrote:
>> On 30 April 2004 11:26, Duncan Coutts wrote:
>>> Could someone remind me what the remaining issues are in getting ghc
>>> to build Haskell modules/packaged into unix .so shared libraries?
>> It might be possible to do this, but only if you want to do
>> dlopen()-style linking at runtime. Linking a haskell binary against
>> Haskell .so libraries still isn't possible - I had another look at
>> this recently, and although one of the obstacles has been removed,
>> there are others (details available on request).
> Details would be interesting.
I can't guarantee that everything in here is correct, but here are the
notes I made last time I looked into the problem:
if anyone has any further thoughts I'd be glad to collect them into a
>> Any remaining issues to do with dlopen()ing a Haskell .so library are
>> probably to do with CAFs. The dynamically loaded code needs to call
>> newDynCAF() instead of newCAF() in a CAF's entry code - this is
>> normally arranged by the RTS linker, but for a .so you'll have to do
>> it some other way, like getting the compiler to emit the different
>> call, or doing some CPP magic (but only for -fvia-C). Any
>> reasonable patches to implement this will be incorporated.
> Does that involve changing what reference get linked to which symbols
> or would it be a matter of finding a bunch of symbols & calling them
> after doing a dlopen() ? Another way of asking the same thing is can
> the calling newDynCAF be done in a separate phase (ie after dlopen())
> or is it intimately part of the linking process?
It is done when a CAF is entered for the first time, so it would be
difficult to do at link time.
The real problem is that the garbage collector has no idea which CAFs
are still reachable in dynamically linked code. For GHCi, we retain
*all* CAFs in dynamically linked code for this reason. This is done by
arranging that all dynamically loaded CAFs get placed on a list when
they are first entered - this is what newDynCAF() does. If you load
code using GHC's linker then this is the behaviour you get.
A workaround for the problem, if you're not using GHC's linker, is to
make StablePtrs for each of the functions you're going to call in the
dynamically loaded code. This will ensure that the GC retains all CAFs
reachable from those functions. Perhaps the dynamic linking library
should do this?
More information about the Glasgow-haskell-users