You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by yl...@apache.org on 2025/08/21 14:22:52 UTC
svn commit: r1927951 - in apr/apr/branches/1.7.x: . memory/unix
Author: ylavic
Date: Thu Aug 21 14:22:52 2025
New Revision: 1927951
Log:
apr_pools: Follow up to r1927658.
In apr_pool_create_ex_debug(), attaching the pool to its parent before creating
the mutex races with other threads running apr_pool_walk_tree() on any ancestor
and finding the pool and crashing on pool_lock() with ->mutex == NULL.
Fix this by moving back the attachment after the mutex is created.
To prevent apr_pool_check_lifetime() failing when the ->mutex is created in
apr_pool_create_ex_debug() with no ->parent (per r1927658), let's make it
ignore pools with ->parent == NULL. This covers both the global pool, all the
unmanaged pools and finally the internal case in apr_pool_create_ex_debug().
There is no way for any other pool to have ->parent == NULL since it's forced
to the global_pool when no parent is given.
* memory/unix/apr_pools.c
(struct apr_pool_t): Remove the "unmanaged" flag since it's no longer used,
unmanaged pools have their ->parent == NULL.
(apr_pool_check_lifetime): Ignore pools with ->parent == NULL, which covers
all the cases.
(apr_pool_create_ex_debug): Move back setting the ->parent after the ->mutex
is created.
(apr_pool_create_unmanaged_ex_debug): Free the owned allocator if the ->mutex
creation failed.
apr_pools: abort() if creating the pool mutex failed (APR_POOL_DEBUG mode).
* memory/unix/apr_pools.c
(apr_pool_create_ex_debug): Call abort_fn if any.
(apr_pool_create_unmanaged_ex_debug): Call abort_fn if any.
Merges r1927948, r1927949 from trunk
Merges r1927950 from ^/apr/apr/branches/1.8.x
Modified:
apr/apr/branches/1.7.x/ (props changed)
apr/apr/branches/1.7.x/memory/unix/apr_pools.c
Modified: apr/apr/branches/1.7.x/memory/unix/apr_pools.c
==============================================================================
--- apr/apr/branches/1.7.x/memory/unix/apr_pools.c Thu Aug 21 14:21:18 2025 (r1927950)
+++ apr/apr/branches/1.7.x/memory/unix/apr_pools.c Thu Aug 21 14:22:52 2025 (r1927951)
@@ -590,7 +590,6 @@ struct apr_pool_t {
apr_os_thread_t owner;
apr_thread_mutex_t *mutex;
#endif /* APR_HAS_THREADS */
- int unmanaged;
#endif /* APR_POOL_DEBUG */
#ifdef NETWARE
apr_os_proc_t owner_proc;
@@ -1605,9 +1604,14 @@ static void apr_pool_check_lifetime(apr_
* ok, since the only user is apr_pools.c. Unless
* people have searched for the top level parent and
* started to use that...
+ * Like the global pool, unmanaged pools have their
+ * own lifetime and no ->parent, ignore both here.
+ * Last (internal) case is from apr_pool_create_ex_debug()
+ * where pool->mutex is created before attaching to the
+ * parent, hence an allocation happens with no ->parent
+ * nor lifetime to be checked here.
*/
- if (pool == global_pool || global_pool == NULL
- || (pool->parent == NULL && pool->unmanaged))
+ if (pool->parent == NULL)
return;
/* Lifetime
@@ -2037,22 +2041,6 @@ APR_DECLARE(apr_status_t) apr_pool_creat
pool->owner_proc = (apr_os_proc_t)getnlmhandle();
#endif /* defined(NETWARE) */
- if ((pool->parent = parent) != NULL) {
- pool_lock(parent);
-
- if ((pool->sibling = parent->child) != NULL)
- pool->sibling->ref = &pool->sibling;
-
- parent->child = pool;
- pool->ref = &parent->child;
-
- pool_unlock(parent);
- }
- else {
- pool->sibling = NULL;
- pool->ref = NULL;
- }
-
#if APR_HAS_THREADS
if (parent == NULL || parent->allocator != allocator) {
apr_status_t rv;
@@ -2067,6 +2055,8 @@ APR_DECLARE(apr_status_t) apr_pool_creat
*/
if ((rv = apr_thread_mutex_create(&pool->mutex,
APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) {
+ if (abort_fn)
+ abort_fn(rv);
free(pool);
return rv;
}
@@ -2076,6 +2066,22 @@ APR_DECLARE(apr_status_t) apr_pool_creat
}
#endif /* APR_HAS_THREADS */
+ if ((pool->parent = parent) != NULL) {
+ pool_lock(parent);
+
+ if ((pool->sibling = parent->child) != NULL)
+ pool->sibling->ref = &pool->sibling;
+
+ parent->child = pool;
+ pool->ref = &parent->child;
+
+ pool_unlock(parent);
+ }
+ else {
+ pool->sibling = NULL;
+ pool->ref = NULL;
+ }
+
#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
apr_pool_log_event(pool, "CREATE", file_line, 1);
#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */
@@ -2113,7 +2119,6 @@ APR_DECLARE(apr_status_t) apr_pool_creat
memset(pool, 0, SIZEOF_POOL_T);
- pool->unmanaged = 1;
pool->abort_fn = abort_fn;
pool->tag = file_line;
pool->file_line = file_line;
@@ -2150,6 +2155,11 @@ APR_DECLARE(apr_status_t) apr_pool_creat
*/
if ((rv = apr_thread_mutex_create(&pool->mutex,
APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) {
+ if (abort_fn)
+ abort_fn(rv);
+ /* Free the allocator created/owned above eventually */
+ if (pool_allocator->owner == pool)
+ apr_allocator_destroy(pool_allocator);
free(pool);
return rv;
}