Index: subversion/libsvn_fs_base/bdb/env.c =================================================================== --- subversion/libsvn_fs_base/bdb/env.c (revision 24473) +++ subversion/libsvn_fs_base/bdb/env.c (working copy) @@ -355,12 +355,12 @@ static volatile svn_atomic_t bdb_cache_state; static svn_error_t * -bdb_init_cb(void) +bdb_init_cb(apr_pool_t *pool) { #if APR_HAS_THREADS apr_status_t apr_err; #endif - bdb_cache_pool = svn_pool_create(NULL); + bdb_cache_pool = svn_pool_create(pool); bdb_cache = apr_hash_make(bdb_cache_pool); #if APR_HAS_THREADS apr_err = apr_thread_mutex_create(&bdb_cache_lock, @@ -380,9 +380,9 @@ } svn_error_t * -svn_fs_bdb__init(void) +svn_fs_bdb__init(apr_pool_t* pool) { - SVN_ERR(svn_atomic__init_once(&bdb_cache_state, bdb_init_cb)); + SVN_ERR(svn_atomic__init_once(&bdb_cache_state, bdb_init_cb, pool)); return SVN_NO_ERROR; } Index: subversion/libsvn_fs_base/bdb/env.h =================================================================== --- subversion/libsvn_fs_base/bdb/env.h (revision 24473) +++ subversion/libsvn_fs_base/bdb/env.h (working copy) @@ -102,7 +102,7 @@ /* Iniitalize the BDB back-end's private stuff. */ -svn_error_t *svn_fs_bdb__init(void); +svn_error_t *svn_fs_bdb__init(apr_pool_t* pool); /* Allocate the Berkeley DB descriptor BDB and open the environment. Index: subversion/libsvn_fs_base/fs.c =================================================================== --- subversion/libsvn_fs_base/fs.c (revision 24473) +++ subversion/libsvn_fs_base/fs.c (working copy) @@ -1195,8 +1195,8 @@ }; svn_error_t * -svn_fs_base__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable) +svn_fs_base__init2(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, apr_pool_t* pool) { static const svn_version_checklist_t checklist[] = { @@ -1213,7 +1213,7 @@ loader_version->major); SVN_ERR(svn_ver_check_list(base_version(), checklist)); SVN_ERR(check_bdb_version()); - SVN_ERR(svn_fs_bdb__init()); + SVN_ERR(svn_fs_bdb__init(pool)); *vtable = &library_vtable; return SVN_NO_ERROR; Index: subversion/include/svn_fs.h =================================================================== --- subversion/include/svn_fs.h (revision 24473) +++ subversion/include/svn_fs.h (working copy) @@ -87,7 +87,10 @@ * effort to bootstrap a mutex for protecting data common to FS * objects; however, there is a small window of failure. Also, a * small amount of data will be leaked if the Subversion FS library is - * dynamically unloaded. + * dynamically unloaded, and using the bdb FS can potentially segfault + * or invoke other undefined behavior if this function is not called + * with an appropriate pool (such as the pool the module was loaded into) + * when loaded dynamically. * * If this function is called multiple times before the pool passed to * the first call is destroyed or cleared, the later calls will have Index: subversion/include/private/svn_atomic.h =================================================================== --- subversion/include/private/svn_atomic.h (revision 24473) +++ subversion/include/private/svn_atomic.h (working copy) @@ -100,13 +100,14 @@ * * @a global_status must be a pointer to a global, zero-initialized * #svn_atomic_t. @a init_func is a pointer to the function that performs - * the actual initialization. + * the actual initialization, and @a pool is passed on to the init_func + * for its use. * * @since New in 1.5. */ svn_error_t * svn_atomic__init_once(volatile svn_atomic_t *global_status, - svn_error_t *(*init_func)(void)); + svn_error_t *(*init_func)(apr_pool_t*), apr_pool_t* pool); #ifdef __cplusplus } Index: subversion/libsvn_fs/fs-loader.h =================================================================== --- subversion/libsvn_fs/fs-loader.h (revision 24473) +++ subversion/libsvn_fs/fs-loader.h (working copy) @@ -101,19 +101,24 @@ library vtable. The LOADER_VERSION parameter must remain first in the list, and the function must use the C calling convention on all platforms, so that the init functions can safely read the version - parameter. + parameter. The POOL parameter must be a pool with a greater + lifetime than the fs module so that fs global state can be kept + in it and cleaned up on termination before the fs module is unloaded. ### need to force this to be __cdecl on Windows... how?? */ typedef svn_error_t *(*fs_init_func_t)(const svn_version_t *loader_version, - fs_library_vtable_t **vtable); + fs_library_vtable_t **vtable, + apr_pool_t* pool); /* Here are the declarations for the FS module init functions. If we are using DSO loading, they won't actually be linked into - libsvn_fs. */ -svn_error_t *svn_fs_base__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable); -svn_error_t *svn_fs_fs__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable); + libsvn_fs. Note that these private functions have been revved to + svn_fs_*__init2 in order to add a pool parameter that may be + used for fs module scoped variables such as the bdb cache. */ +svn_error_t *svn_fs_base__init2(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, apr_pool_t* pool); +svn_error_t *svn_fs_fs__init2(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, apr_pool_t* pool); Index: subversion/libsvn_fs/fs-loader.c =================================================================== --- subversion/libsvn_fs/fs-loader.c (revision 24473) +++ subversion/libsvn_fs/fs-loader.c (working copy) @@ -61,14 +61,14 @@ { SVN_FS_TYPE_BDB, "base", #ifdef SVN_LIBSVN_FS_LINKS_FS_BASE - svn_fs_base__init + svn_fs_base__init2 #endif }, { SVN_FS_TYPE_FSFS, "fs", #ifdef SVN_LIBSVN_FS_LINKS_FS_FS - svn_fs_fs__init + svn_fs_fs__init2 #endif }, @@ -131,7 +131,33 @@ _("Failed to load module for FS type '%s'"), fst->fs_type); - SVN_ERR(initfunc(my_version, vtable)); + { + apr_status_t status; + + /* Per our API compatibility rules, we cannot ensure that + svn_fs_initialize is called by the application. If not, we + cannot create the common pool and lock in a thread-safe fashion, + nor can we clean up the common pool if libsvn_fs is dynamically + unloaded. This function makes a best effort by creating the + common pool as a child of the global pool; the window of failure + due to thread collision is small. */ + if (!common_pool) + SVN_ERR(svn_fs_initialize(NULL)); + + /* Invoke the FS module's initfunc function with the common + pool protected by a lock. */ +#if APR_HAS_THREADS + status = apr_thread_mutex_lock(common_pool_lock); + if (status) + return svn_error_wrap_apr(status, _("Can't grab FS mutex")); +#endif + SVN_ERR(initfunc(my_version, vtable, common_pool)); +#if APR_HAS_THREADS + status = apr_thread_mutex_unlock(common_pool_lock); + if (status) + return svn_error_wrap_apr(status, _("Can't ungrab FS mutex")); +#endif + } fs_version = (*vtable)->get_version(); if (!svn_ver_equal(my_version, fs_version)) return svn_error_createf(SVN_ERR_VERSION_MISMATCH, NULL, @@ -271,16 +297,6 @@ apr_status_t status; #endif - /* Per our API compatibility rules, we cannot ensure that - svn_fs_initialize is called by the application. If not, we - cannot create the common pool and lock in a thread-safe fashion, - nor can we clean up the common pool if libsvn_fs is dynamically - unloaded. This function makes a best effort by creating the - common pool as a child of the global pool; the window of failure - due to thread collision is small. */ - if (!common_pool) - SVN_ERR(svn_fs_initialize(NULL)); - /* Invoke the FS module's serialized_init function with the common pool protected by a lock. */ #if APR_HAS_THREADS Index: subversion/libsvn_subr/atomic.c =================================================================== --- subversion/libsvn_subr/atomic.c (revision 24473) +++ subversion/libsvn_subr/atomic.c (working copy) @@ -26,7 +26,7 @@ svn_error_t* svn_atomic__init_once(volatile svn_atomic_t *global_status, - svn_error_t *(*init_func)(void)) + svn_error_t *(*init_func)(apr_pool_t*), apr_pool_t* pool) { /* We have to call init_func exactly once. Because APR doesn't have statically-initialized mutexes, we implement a poor @@ -37,7 +37,7 @@ if (status == SVN_ATOMIC_UNINITIALIZED) { - svn_error_t *err = init_func(); + svn_error_t *err = init_func(pool); if (err) { #ifdef APR_HAS_THREADS Index: subversion/libsvn_fs_fs/fs.c =================================================================== --- subversion/libsvn_fs_fs/fs.c (revision 24473) +++ subversion/libsvn_fs_fs/fs.c (working copy) @@ -307,8 +307,8 @@ }; svn_error_t * -svn_fs_fs__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable) +svn_fs_fs__init2(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, apr_pool_t* pool) { static const svn_version_checklist_t checklist[] = {