summaryrefslogtreecommitdiff
path: root/threadproc/beos
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2020-12-03 22:59:01 +0000
committerYann Ylavic <ylavic@apache.org>2020-12-03 22:59:01 +0000
commitf543ad132fe65bf6f570bd2fe4f3d12bf044d211 (patch)
tree4741d6d0d59345675e009f630ebcc292a89c83c6 /threadproc/beos
parentee6a4a8ba864740c7f3fbc331d197d260e1504a5 (diff)
downloadapr-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.c38
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;
}