summaryrefslogtreecommitdiff
path: root/threadproc/win32/thread.c
diff options
context:
space:
mode:
authorylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2020-12-03 22:59:01 +0000
committerylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2020-12-03 22:59:01 +0000
commit6a3bad72a1d183453bc0817a54307562af18c531 (patch)
tree4741d6d0d59345675e009f630ebcc292a89c83c6 /threadproc/win32/thread.c
parent0263edddcbee915f7058c778cafa1d6932404261 (diff)
downloadlibapr-6a3bad72a1d183453bc0817a54307562af18c531.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/win32/thread.c')
-rw-r--r--threadproc/win32/thread.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c
index 757a9f0d5..b5a6f1722 100644
--- a/threadproc/win32/thread.c
+++ b/threadproc/win32/thread.c
@@ -28,6 +28,9 @@
/* Chosen for us by apr_initialize */
DWORD tls_apr_thread = 0;
+/* 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)
{
@@ -103,7 +106,31 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
(*new)->data = data;
(*new)->func = func;
- stat = apr_pool_create(&(*new)->pool, pool);
+
+ if (attr && attr->detach) {
+ 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;
}
@@ -187,6 +214,8 @@ APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
}
if (CloseHandle(thd->td)) {
+ /* Detach from the parent pool too */
+ apr__pool_unmanage(thd->pool);
thd->td = NULL;
return APR_SUCCESS;
}