Howard Chu wrote:
Darryl Miles wrote:
Still don't get it. Lets use Linux as an example.
This is actually one of the easiest to solve. Of course the bigger
problem is that solutions here are all platform-dependent, and
maintenance will be a pain.
ELF shared libraries support .init and .fini sections to contain code
that should be executed just after load and just before unload. Assuming
you had a default set of callbacks in the library, it would be simple to
set them here. Likewise any other shared library that manipulates
callbacks can do its own cleanup safely in their own .fini section.
The other feature you need, to make this reasonable, is support for weak
external symbols. I don't know of any compiler support for these but
certainly they're supported at the assembler and linker level. The
default callbacks should reference pthread functions as weak externs,
and just no-op if the externs are unresolved at runtime.
Since a dynamic linker requires the use of threading primitives (mutexes
and such) internally (if itself supports multi-threaded usage) it is
highly likely it has access to an implementation to advise from the
.init and .fini.
So the next matter would be for the .init and .fini functions to provide
a reference back to the dynamic linker as an argument when those
callbacks get invoked. I shall call this the "module handle".
From this "module handle" the dynamic linker needs to provide API
accessible implementations for:
* Symbol lookup (maybe this is already extern and implicitly available
to all DSOs)
* Mutex API (init, lock, unlock, trylock, end, sizeof())
* Reference counting increment/decrement API (init, increment,
decrement, end, sizeof()) - To be honest this can be written on top of
a mutex, everything can be built on top of a working mutex, but exposing
an API for something obviously useful here might stop wheel reinvention!
[FWIW - The sizeof() relates to the amount of space required for opaque
storage, in the interests of future proofing and the fact these are not
performance implementations more space than is required should be
reserved and 64bit should be reserving double the amount 32bit does]
Just to reiterate the major point of this reply ... THE DYNAMIC LINKER
NEEDS TO PROVIDE API ....
What I think I need to clarify is that from the module's point of view
it is the dynamic linker which is providing the implementations, not
libpthread. The fact these function pointers may directly access an
already mapped copy of similar libpthread function/symbols in some
platforms should be treated as a coincidence. Infact I would probably
advocate not doing that and having libdl at least use a delegation
pattern internally to allow a shim layer to iron out minor differences
between APIs (the mutex API is exposes and the mutex API is consumes).
I'm trying to remove the notion of a "symbol" out of it, since the
module (OpenSSL) can not assume any particular mutex implementation such
as POSIX Threads. It doesn't matter what the implementation is it just
needs an API provided by the dynamic linker. This means OpenSSL doesn't
directly access POSIX Thread definitions at compile time for this
purpose, it references some definitions supplied by <dlfcn.h>.
If you start using weak symbols, then you end up down the route of
making OpenSSL responsible for knowing about and at runtime trying to
detect which mutex implementation exists and is available. This is the
whole matter I'm trying to clearly push back to the dynamic linker.
This is not OpenSSL's problem!
Darryl
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majord...@openssl.org