diff options
author | Yann Ylavic <ylavic@apache.org> | 2020-12-03 22:59:01 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2020-12-03 22:59:01 +0000 |
commit | f543ad132fe65bf6f570bd2fe4f3d12bf044d211 (patch) | |
tree | 4741d6d0d59345675e009f630ebcc292a89c83c6 /threadproc/beos | |
parent | ee6a4a8ba864740c7f3fbc331d197d260e1504a5 (diff) | |
download | apr-f543ad132fe65bf6f570bd2fe4f3d12bf044d211.tar.gz |
apr_thread: use unmanaged pools for detached threads.
A detached thread is by definition out of control, unjoinable, unmanaged,
and it can terminate/exit after its parent pool is detroyed.
To avoid use-after-free in this case, let's use an unmanaged pool for detached
threads, either by creating an unmanaged pool from the start if the thread
is created detached, or by "unmanaging" the pool if the thread is detached
later with apr_thread_detach().
To "umanage" the pool, provide a new internal helper, apr__pool_unmanage()
which takes care of removing the pool from its parent's list.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1884078 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'threadproc/beos')
-rw-r--r-- | threadproc/beos/thread.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 61d7fd0d7..c1509da26 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -17,6 +17,9 @@ #include "apr_arch_threadproc.h" #include "apr_portable.h" +/* Internal (from apr_pools.c) */ +extern apr_status_t apr__pool_unmanage(apr_pool_t *pool); + APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool) { (*new) = (apr_threadattr_t *)apr_palloc(pool, @@ -90,7 +93,35 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t (*new)->data = data; (*new)->func = func; (*new)->exitval = -1; + (*new)->detached = (attr && apr_threadattr_detach_get(attr) == APR_DETACH); + if ((*new)->detached) { + stat = apr_pool_create_unmanaged_ex(&(*new)->pool, + apr_pool_abort_get(pool), + NULL); + } + else { + /* The thread can be apr_thread_detach()ed later, so the pool needs + * its own allocator to not depend on the parent pool which could be + * destroyed before the thread exits. The allocator needs no mutex + * obviously since the pool should not be used nor create children + * pools outside the thread. + */ + apr_allocator_t *allocator; + if (apr_allocator_create(&allocator) != APR_SUCCESS) { + return APR_ENOMEM; + } + stat = apr_pool_create_ex(&(*new)->pool, pool, NULL, allocator); + if (stat == APR_SUCCESS) { + apr_allocator_owner_set(allocator, (*new)->pool); + } + else { + apr_allocator_destroy(allocator); + } + } + if (stat != APR_SUCCESS) { + return stat; + } /* First we create the new thread...*/ if (attr) @@ -98,11 +129,6 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t else temp = B_NORMAL_PRIORITY; - stat = apr_pool_create(&(*new)->pool, pool); - if (stat != APR_SUCCESS) { - return stat; - } - (*new)->td = spawn_thread((thread_func)dummy_worker, "apr thread", temp, @@ -169,6 +195,8 @@ APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) } if (suspend_thread(thd->td) == B_NO_ERROR) { + /* Detach from the parent pool too */ + apr__pool_unmanage(thd->pool); thd->detached = 1; return APR_SUCCESS; } |