We dynamically load libraries. Whee! Yay, us. We need a set of
semantics defined and an API to go with them so we can meaningfully
and reliably work with them.
So, to start, here are the semantics I think we're going to need to
have -- when we hash these out we'll define the API to do it. Note
that for many libraries these functions will either pitch an
exception or do nothing. Also note that unless the library's
specifically built for parrot some of these functions won't be
available and will have to be provided by parrot.
1) Load the shared library from disk
The equivalent of dlopen. (May well *be* dlopen)
2) Globally initialize the shared library
The function called to get the library all initialized
3) Per-thread pool initialize the shared library
The function called in the library to set it up for use in the
current thread pool. (The thread pool is all the parrot threads that
are sharing data)
4) Per-thread initialize the shared library
The function called in each OS thread to initialize the shared library
5) Re-initialize the shared library
The function we call to globally re-initialize the library
6) Unload the shared library
The function we call to unload the library from memory.
7) Register the library with parrot
This function gets us a library PMC to wrap the library.
We'll likely find very few libraries that do all of these -- I'm not
sure there are any libraries that need per-thread initialization, but
I'm throwing it in since it's a lot easier to plan for it then stub
it out later than it is to add it in later.
We're also going to want to allow embedding applications to pass in
handles to existing libraries (so, for example, we don't try and load
in half a dozen versions of the expat library...) that it's already
loaded in.
--
Dan
--------------------------------------it's like this-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
Nope, and that won't work once things get split out into version
directories either -- that'd potentially a *lot* of directories in
LD_LIBRARY_PATH, directores that may get added to at runtime.
I think the only thing we can reasonably do is leave library loading
order up to module authors (if you need module X, then load it in)
unless we want to define autoloaded dependencies (where a module
registers that it needs X and we load it if it's not already in) but
I'm not at all comfortable with that. Neither saves us from circular
dependencies but, then, nothing will.
When the library loading API's defined and multiple PMCs can be
bundled together into a single library I think it may well help
ameliorate many of the potential problems we'll hit with this.
I tried it. Doesn't work. So I guess there's no point in having the API
entry.
That reminds me, I was reading P6&PE yesterday, and I came across a
scary bit on loading of shared libraries. The statement was made that
Parrot would search the current directory first.
Perhaps this was an over-simplification, but if not, PLEASE,
re-consider. Security implications aside (and they're huge), Parrot
should probably be searching its installation area (possibly overridden
by an environment variable) followed by whatever system path (e.g.
LD_LIBRARY_PATH, ldconfig or whatever your OS uses) is given to Parrot
externally, so as not to modify the behavior of a program based on the
current directory of the user running it.
It does? Urk. No, not by default. We need to work out some library
loading stuff, but this is *definitely* not going to be the default.