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

Reply via email to