On 25.07.2018 17:46, William A Rowe Jr wrote:
> Giving this problem some thought...
> If an aprfoo-1.so provider is linked to the libfoo.so library, and we
> track the init state and perform it only once, it seems that apr
> should never try to de-init or unload the .so provider for the
> lifespan of the process.
> This should help us avoid some redundant initialization. While we
> could free resources atexit()

Shared libraries (remember, APR is usually a shared lib too) should
avoid using the atexit() mechanism. It's a good way to shoot yourself in
the foot; on Unix, you *may*, depending on the platform, have the
atexit() handlers run in a predictable order. But on Windows, each DLL
has its own atexit() queue and all predictability goes out the window.

> , any spin of trying to repeatedly unload and reload any .so provider
> seems to be inherently messy and unstable. We see this issue with
> mod_ssl, etc, where the statics may be freed and reinitialized, and
> causes the resource leakage mentioned by Yann.

Yes, unloading a DSO that wasn't designed for it is always messy, and
probably always wrong, too.

> Once loaded and initialized, we recieve no benefit from repeatedly
> altering the processes' library mmaps, and doing so after we spin up
> contending threads is an even worse scenario. Leaving them loaded
> should not have an adverse effect, and if it becomes swapped out due
> to lack of use during the lifespan of the process, should not be
> particularly harmful.
> While httpd modules are often unloaded and reloaded, the underlying
> libfoo.so is still stuck in process to libapr-1.so, so those should
> remain stable.
> Does this make sense?

Yes, however: apr_dso_load() takes a pool as context, and when the pool
is destroyed, all the related DSO modules are unloaded, whether you want
them to be or not. Even using a global pool for apr_dso_load() does not
help because you still will have no control of the lifetime of other
pools or code that may still be live and depend on the DSO module when
it's unloaded at global pool cleanup time.

We've had constant and painful problems with this in Subversion, having
to track down random crashes at process exit. We've implemented really
horrible workarounds, and I'm still not sure we've covered every edge case.

APR should either stop using pools in the apr_dso_* implementation --
it's better to malloc() the apr_dso_handle_t and risk its leaking than
to randomly break code -- or it should provide a type of pool that is
never cleaned up for this purpose. But I think the former is better.

-- Brane

Reply via email to