apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Garrett Rooney" <roo...@electricjellyfish.net>
Subject Problems with DSOs and Pools
Date Fri, 11 Aug 2006 16:42:32 GMT
We've been fighting with some DSO/Pool related bugs in Subversion
lately, and have basically come to the conclusion that there's no good
solution, or at least no good solution that doesn't involve patching
APR itself.

The problem, in short, is that when you use a pool to load a DSO you
need to make sure that the pool lives longer than any code that might
call a function within the DSO.  This is simple enough with most
things, but when the code inside the DSO makes use of pools,
specifically pool cleanups, you can easily end up in situations where
you've set up a cleanup (which calls a function defined inside the
DSO) on a pool that will outlive the pool used to open the DSO.  This
means that by the time you call that cleanup function the DSO is
unloaded, so all sorts of badness ensues.

The timeline for this sort of thing looks like this:

1. Create application pool (global scope).
2. In another global pool open up a DSO.
3. Call a function defined in the DSO, passing in your application pool.
4. The function inside the DSO registers a cleanup on the application pool.
5. The program finishes, and apr_terminate is called.
6. Global pools are destroyed in a last-in first-out manner, so the
pool used to load the DSO is destroyed (and the DSO is unloaded)
before the application pool, madness ensues.

So if you're going to pass pools into a function within a DSO you
basically need to make sure that the DSO is loaded in an older pool,
to be 100% sure it has to be a pool that's older than ANY other pool.

Possible solutions include:

1) Just use the global top level pool to load the DSO.  This sounds
great, but is not thread safe, so it's a no-no.
2) Create yourself a global pool to load DSOs into, and do so early
enough that it'll always be destroyed last.  This works if you have
control over the entire program, but basically means you need to do
this immediately after apr_initialize(), which may not always be
possible (what if you're a library, or you're running inside of a
httpd module, etc).

Basically, what I'd like to do is add a new API (say,
apr_dso_load_permanently, or hopefully something with a better name
than that) which will load DSOs into a new global pool that's created
during apr_initialize(), it'll be the first pool created after the
global top level APR pool, and thus it'll be certain to outlive any
application created pool.  The dsos will only be unloaded at
apr_terminate time, when their global pool is destroyed, but honestly,
that's what I want in this situation anyway, as it's impossible to be
sure that users of your API haven't done unfortunate things with pools
that make unloading the DSO dangerous anyway.



View raw message