|
From: stephan b. <st...@s1...> - 2004-12-23 23:17:42
|
On Thursday 23 December 2004 23:55, Christian Prochnow wrote:
> Am Donnerstag 23 Dezember 2004 22:08 schrieb stephan beal:
> > Yo!
> >
> > i'm adding SharedLib.ltdl.cpp (uses GNU libltdl, portable libdl
> > replacement) and i noticed this code in SharedLib.dl.cpp:
>
> which other DLL APIs does libltdl support ? i thought we catched
> every DLL API with the existing dl, shl, dyld and win32
> implementations !?
It's not a question of whether libltdl supports another lib loader.
Suppose i open Foo.so. Foo.so can run arbitrary code and IT can use,
e.g., dlopen(). If SharedLib dlcloses() in the dtor then we close
Foo.so, but the libs dlopen()ed by Foo.so might not be shut down. Those
dlls might leave artefacts in memory which we still rely on, like
object factories.
> While this is a problem with the CL architecture .. in general it is
> not. In fact, when DLLs are unloaded which register themselves upon
> loading, they should also deregister themselves from the CL.
That assumes that the DLL knows how to do so. AFAIK this is
loader-dependent. e.g., libdl looks for the symbol _fine() (i think
that's the name) and calls if it exists. We can't ask loadable classes
to know what dlopen implementation they're using.
> Anyway for objects created within the loaded DLL you're right, it
> would be unpractial to keep track of ownership and to destroy all
> instances created form within the DLL we're unloading. Do you think
> it is possible to "transfer" ownership of objects allocated in DLLs
> to the app ?
"Jein".
This is difficult to answer without giving some details about the CL
model. Here's how a CL lookup works:
a) Do we have a factory for KEY? If so, run that factory.
b) Can we find a DLL for KEY.so? If so, open it. The static-init phase
of the DLL triggers factory registrations living in that DLL. They
simply call Factory<InterfaceT>::registerxxxx("myclassname",myfactory).
c) Repeat (a). If we have no factory, return 0. The DLL did not have
what we wanted, so we could ARGUABLY dlclose() it, but the fact is that
we cannot know what other DLLs it has opened, and this HAS causes
crashes for me in real use cases.
What this means is that the DLLs register themselves with the factory,
without the factory actually having to know. Opening ANY DLL can
trigger an arbitrary number of factory registrations. Consider doing
this in your app's init code:
P::System::openSharedLib( "/path/to/my_common_classes.so" );
That might have just registered 27 classes across 5 different factories.
And it might not have done anything at all!
As far as SharedLib ownership goes: see the impl of openSharedLibrary()
SharedLib.generic.cpp. i believe that one is relatively sane, and it
works using the platform-defined SharedLib.
> This is not a problem. In fact SharedLib owns the pointers one can
> retrieve with the operator[]. If this is documented everything is
> fine.
i'm not thinking about symbol-level access. i'm thinking about the
factories which were registered via static-init. If dlclose() is
called, those factories point to nirgendwo, or maybe even point to some
other valid memory after the next dlopen! Eeeek!
> DLLs have a "init" and "shutdown" function. Maybe the Factory
> pointers can be removed by the shutdown function when unloading the
> DLL.
That's lib-loader-dependent. That means the static init code must know
what loader it's using. The static init code normally looks like the
following global-scope code, and is 100% symbol/load-independent:
void my_init() {
... register my factories ...
}
int my_init_placeholder = (my_init(),0);
That is how we achieve 100% symbol-ignorance in the CL registration
layer.
--
----- st...@s1... http://s11n.net
"...pleasure is a grace and is not obedient to the commands
of the will." -- Alan W. Watts
|