I presume this is covered under our prior conversation about adding API's to a subrevision, and is resolved?
On Wed, Jan 19, 2022 at 11:06 AM <yla...@apache.org> wrote: > > Author: ylavic > Date: Wed Jan 19 17:06:36 2022 > New Revision: 1897210 > > URL: http://svn.apache.org/viewvc?rev=1897210&view=rev > Log: > apr_thread: Follow up to r1884078: Unmanaged pools for attached threads too. > > [Note 1.7.x: this removes apr__pool_unmanage() thus r1884103's ABI issues] > > r1884078 fixed lifetime issues with detached threads by using unmanaged pool > destroyed by the thread itself on exit, with no binding to the parent pool. > > This commit makes use of unmanaged pools for attached threads too, they needed > their own allocator anyway due to apr_thread_detach() being callable anytime > later. apr__pool_unmanage() was a hack to detach a subpool from its parent, > but > if a subpool needs its own allocator for this to work correctly there is no > point in creating a subpool for threads (no memory reuse on destroy for short > living threads for instance). > > Since an attached thread has its own lifetime now, apr_thread_join() must be > called to free its resources/pool, though it's no different than before when > destroying the parent pool was UB if the thread was still running (i.e. not > joined yet). > > Let's acknoledge that threads want no binding with the pool passed to them at > creation time, besides the abort_fn which they can steal :) > > > Merges r1897179 from trunk. > Submitted by: ylavic > > Modified: > apr/apr/branches/1.7.x/ (props changed) > apr/apr/branches/1.7.x/memory/unix/apr_pools.c > apr/apr/branches/1.7.x/threadproc/beos/thread.c > apr/apr/branches/1.7.x/threadproc/netware/thread.c > apr/apr/branches/1.7.x/threadproc/os2/thread.c > apr/apr/branches/1.7.x/threadproc/unix/thread.c > apr/apr/branches/1.7.x/threadproc/win32/thread.c > > Propchange: apr/apr/branches/1.7.x/ > ------------------------------------------------------------------------------ > Merged /apr/apr/trunk:r1897179 > > Modified: apr/apr/branches/1.7.x/memory/unix/apr_pools.c > URL: > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/memory/unix/apr_pools.c?rev=1897210&r1=1897209&r2=1897210&view=diff > ============================================================================== > --- apr/apr/branches/1.7.x/memory/unix/apr_pools.c (original) > +++ apr/apr/branches/1.7.x/memory/unix/apr_pools.c Wed Jan 19 17:06:36 2022 > @@ -2324,45 +2324,6 @@ APR_DECLARE(void) apr_pool_lock(apr_pool > > #endif /* !APR_POOL_DEBUG */ > > -/* For APR internal use only (for now). > - * Detach the pool from its/any parent (i.e. un-manage). > - */ > -apr_status_t apr__pool_unmanage(apr_pool_t *pool); > -apr_status_t apr__pool_unmanage(apr_pool_t *pool) > -{ > - apr_pool_t *parent = pool->parent; > - > - if (!parent) { > - return APR_NOTFOUND; > - } > - > -#if APR_POOL_DEBUG > - if (pool->allocator && pool->allocator == parent->allocator) { > - return APR_EINVAL; > - } > - apr_thread_mutex_lock(parent->mutex); > -#else > - if (pool->allocator == parent->allocator) { > - return APR_EINVAL; > - } > - allocator_lock(parent->allocator); > -#endif > - > - /* Remove the pool from the parent's children */ > - if ((*pool->ref = pool->sibling) != NULL) { > - pool->sibling->ref = pool->ref; > - } > - pool->parent = NULL; > - > -#if APR_POOL_DEBUG > - apr_thread_mutex_unlock(parent->mutex); > -#else > - allocator_unlock(parent->allocator); > -#endif > - > - return APR_SUCCESS; > -} > - > #ifdef NETWARE > void netware_pool_proc_cleanup () > { > > Modified: apr/apr/branches/1.7.x/threadproc/beos/thread.c > URL: > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/threadproc/beos/thread.c?rev=1897210&r1=1897209&r2=1897210&view=diff > ============================================================================== > --- apr/apr/branches/1.7.x/threadproc/beos/thread.c (original) > +++ apr/apr/branches/1.7.x/threadproc/beos/thread.c Wed Jan 19 17:06:36 2022 > @@ -17,9 +17,6 @@ > #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, > @@ -83,63 +80,56 @@ APR_DECLARE(apr_status_t) apr_thread_cre > { > int32 temp; > apr_status_t stat; > + apr_allocator_t *allocator; > > (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > if ((*new) == NULL) { > return APR_ENOMEM; > } > > - (*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); > - } > + /* The thread can be detached anytime (from the creation or later with > + * apr_thread_detach), so it needs its own pool and allocator to not > + * depend on a 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. > + */ > + stat = apr_allocator_create(&allocator); > + if (stat != APR_SUCCESS) { > + return stat; > } > + stat = apr_pool_create_unmanaged_ex(&(*new)->pool, > + apr_pool_abort_get(pool), > + allocator); > if (stat != APR_SUCCESS) { > + apr_allocator_destroy(allocator); > return stat; > } > + apr_allocator_owner_set(allocator, (*new)->pool); > > - /* First we create the new thread...*/ > - if (attr) > - temp = attr->attr; > - else > - temp = B_NORMAL_PRIORITY; > + (*new)->data = data; > + (*new)->func = func; > + (*new)->exitval = -1; > + (*new)->detached = (attr && apr_threadattr_detach_get(attr) == > APR_DETACH); > + > + if (attr) > + temp = attr->attr; > + else > + temp = B_NORMAL_PRIORITY; > > + /* First we create the new thread...*/ > (*new)->td = spawn_thread((thread_func)dummy_worker, > "apr thread", > temp, > (*new)); > > /* Now we try to run it...*/ > - if (resume_thread((*new)->td) == B_NO_ERROR) { > - return APR_SUCCESS; > + if (resume_thread((*new)->td) != B_NO_ERROR) { > + stat = errno; > + apr_pool_destroy((*new)->pool); > + return stat; > } > - else { > - return errno; > - } > + > + return APR_SUCCESS; > } > > APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) > @@ -196,8 +186,6 @@ APR_DECLARE(apr_status_t) apr_thread_det > } > > 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; > } > > Modified: apr/apr/branches/1.7.x/threadproc/netware/thread.c > URL: > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/threadproc/netware/thread.c?rev=1897210&r1=1897209&r2=1897210&view=diff > ============================================================================== > --- apr/apr/branches/1.7.x/threadproc/netware/thread.c (original) > +++ apr/apr/branches/1.7.x/threadproc/netware/thread.c Wed Jan 19 17:06:36 > 2022 > @@ -21,9 +21,6 @@ > > static int thread_count = 0; > > -/* Internal (from apr_pools.c) */ > -extern apr_status_t apr__pool_unmanage(apr_pool_t *pool); > - > apr_status_t apr_threadattr_create(apr_threadattr_t **new, > apr_pool_t *pool) > { > @@ -87,14 +84,48 @@ apr_status_t apr_thread_create(apr_threa > { > apr_status_t stat; > unsigned long flags = NX_THR_BIND_CONTEXT; > - char threadName[NX_MAX_OBJECT_NAME_LEN+1]; > size_t stack_size = APR_DEFAULT_STACK_SIZE; > + apr_allocator_t *allocator; > + > + (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > + if ((*new) == NULL) { > + return APR_ENOMEM; > + } > + > + /* The thread can be detached anytime (from the creation or later with > + * apr_thread_detach), so it needs its own pool and allocator to not > + * depend on a 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. > + */ > + stat = apr_allocator_create(&allocator); > + if (stat != APR_SUCCESS) { > + return stat; > + } > + stat = apr_pool_create_unmanaged_ex(&(*new)->pool, > + apr_pool_abort_get(pool), > + allocator); > + if (stat != APR_SUCCESS) { > + apr_allocator_destroy(allocator); > + return stat; > + } > + apr_allocator_owner_set(allocator, (*new)->pool); > > + (*new)->data = data; > + (*new)->func = func; > + (*new)->exitval = -1; > + (*new)->detached = (attr && apr_threadattr_detach_get(attr) == > APR_DETACH); > if (attr && attr->thread_name) { > - strncpy (threadName, attr->thread_name, NX_MAX_OBJECT_NAME_LEN); > + (*new)->thread_name = apr_pstrndup(pool, ttr->thread_name, > + NX_MAX_OBJECT_NAME_LEN); > } > else { > - sprintf(threadName, "APR_thread %04ld", ++thread_count); > + (*new)->thread_name = apr_psprintf(pool, "APR_thread %04d", > + ++thread_count); > + } > + if ((*new)->thread_name == NULL) { > + apr_pool_destroy((*new)->pool); > + return APR_ENOMEM; > } > > /* An original stack size of 0 will allow NXCreateThread() to > @@ -106,45 +137,6 @@ apr_status_t apr_thread_create(apr_threa > stack_size = attr->stack_size; > } > > - (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > - > - if ((*new) == NULL) { > - return APR_ENOMEM; > - } > - > - (*new)->data = data; > - (*new)->func = func; > - (*new)->thread_name = (char*)apr_pstrdup(pool, threadName); > - > - (*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; > - } > - > if (attr && attr->detach) { > flags |= NX_THR_DETACHED; > } > @@ -157,19 +149,21 @@ apr_status_t apr_thread_create(apr_threa > /* unsigned long flags */ NX_CTX_NORMAL, > /* int *error */ &stat); > > - stat = NXContextSetName( > + (void) NXContextSetName( > /* NXContext_t ctx */ (*new)->ctx, > - /* const char *name */ threadName); > + /* const char *name */ (*new)->thread_name); > > stat = NXThreadCreate( > /* NXContext_t context */ (*new)->ctx, > /* unsigned long flags */ flags, > /* NXThreadId_t *thread_id */ &(*new)->td); > > - if (stat == 0) > - return APR_SUCCESS; > + if (stat) { > + apr_pool_destroy((*new)->pool); > + return stat; > + } > > - return(stat); /* if error */ > + return APR_SUCCESS; > } > > apr_os_thread_t apr_os_thread_current() > @@ -224,8 +218,6 @@ apr_status_t apr_thread_detach(apr_threa > return APR_EINVAL; > } > > - /* Detach from the parent pool too */ > - apr__pool_unmanage(thd->pool); > thd->detached = 1; > > return APR_SUCCESS; > > Modified: apr/apr/branches/1.7.x/threadproc/os2/thread.c > URL: > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/threadproc/os2/thread.c?rev=1897210&r1=1897209&r2=1897210&view=diff > ============================================================================== > --- apr/apr/branches/1.7.x/threadproc/os2/thread.c (original) > +++ apr/apr/branches/1.7.x/threadproc/os2/thread.c Wed Jan 19 17:06:36 2022 > @@ -24,8 +24,6 @@ > #include "apr_arch_file_io.h" > #include <stdlib.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) > @@ -70,9 +68,9 @@ APR_DECLARE(apr_status_t) apr_threadattr > return APR_ENOTIMPL; > } > > -static void apr_thread_begin(void *arg) > +static void dummy_worker(void *opaque) > { > - apr_thread_t *thread = (apr_thread_t *)arg; > + apr_thread_t *thread = (apr_thread_t *)opaque; > thread->exitval = thread->func(thread, thread->data); > if (thd->attr->attr & APR_THREADATTR_DETACHED) { > apr_pool_destroy(thread->pool); > @@ -87,70 +85,51 @@ APR_DECLARE(apr_status_t) apr_thread_cre > { > apr_status_t stat; > apr_thread_t *thread; > - > - thread = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > - *new = thread; > - > + apr_allocator_t *allocator; > + > + *new = thread = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > if (thread == NULL) { > return APR_ENOMEM; > } > > - thread->attr = attr; > - thread->func = func; > - thread->data = data; > - > - if (attr && attr->attr & APR_THREADATTR_DETACHED) { > - stat = apr_pool_create_unmanaged_ex(&thread->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(&thread->pool, pool, NULL, allocator); > - if (stat == APR_SUCCESS) { > - apr_thread_mutex_t *mutex; > - stat = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, > - thread->pool); > - if (stat == APR_SUCCESS) { > - apr_allocator_mutex_set(allocator, mutex); > - apr_allocator_owner_set(allocator, thread->pool); > - } > - else { > - apr_pool_destroy(thread->pool); > - } > - } > - if (stat != APR_SUCCESS) { > - apr_allocator_destroy(allocator); > - } > + /* The thread can be detached anytime (from the creation or later with > + * apr_thread_detach), so it needs its own pool and allocator to not > + * depend on a 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. > + */ > + stat = apr_allocator_create(&allocator); > + if (stat != APR_SUCCESS) { > + return stat; > } > + stat = apr_pool_create_unmanaged_ex(&thread->pool, > + apr_pool_abort_get(pool), > + allocator); > if (stat != APR_SUCCESS) { > + apr_allocator_destroy(allocator); > return stat; > } > + apr_allocator_owner_set(allocator, thread->pool); > > + thread->func = func; > + thread->data = data; > if (attr == NULL) { > - stat = apr_threadattr_create(&thread->attr, thread->pool); > - > + stat = apr_threadattr_create(&attr, thread->pool); > if (stat != APR_SUCCESS) { > + apr_pool_destroy(thread->pool); > return stat; > } > } > + thread->attr = attr; > > - thread->tid = _beginthread(apr_thread_begin, NULL, > + thread->tid = _beginthread(dummy_worker, NULL, > thread->attr->stacksize > 0 ? > thread->attr->stacksize : > APR_THREAD_STACKSIZE, > thread); > - > if (thread->tid < 0) { > - return errno; > + stat = errno; > + apr_pool_destroy(thread->pool); > + return stat; > } > > return APR_SUCCESS; > @@ -208,8 +187,6 @@ APR_DECLARE(apr_status_t) apr_thread_det > return APR_EINVAL; > } > > - /* Detach from the parent pool too */ > - apr__pool_unmanage(thd->pool); > thd->attr->attr |= APR_THREADATTR_DETACHED; > > return APR_SUCCESS; > > Modified: apr/apr/branches/1.7.x/threadproc/unix/thread.c > URL: > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/threadproc/unix/thread.c?rev=1897210&r1=1897209&r2=1897210&view=diff > ============================================================================== > --- apr/apr/branches/1.7.x/threadproc/unix/thread.c (original) > +++ apr/apr/branches/1.7.x/threadproc/unix/thread.c Wed Jan 19 17:06:36 2022 > @@ -22,9 +22,6 @@ > > #if APR_HAVE_PTHREAD_H > > -/* Internal (from apr_pools.c) */ > -extern apr_status_t apr__pool_unmanage(apr_pool_t *pool); > - > /* Destroy the threadattr object */ > static apr_status_t threadattr_cleanup(void *data) > { > @@ -159,49 +156,39 @@ APR_DECLARE(apr_status_t) apr_thread_cre > { > apr_status_t stat; > pthread_attr_t *temp; > - > + apr_allocator_t *allocator; > + > (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > - > if ((*new) == NULL) { > return APR_ENOMEM; > } > > - (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t)); > - > - if ((*new)->td == NULL) { > - return APR_ENOMEM; > + /* The thread can be detached anytime (from the creation or later with > + * apr_thread_detach), so it needs its own pool and allocator to not > + * depend on a 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. > + */ > + stat = apr_allocator_create(&allocator); > + if (stat != APR_SUCCESS) { > + return stat; > } > + stat = apr_pool_create_unmanaged_ex(&(*new)->pool, > + apr_pool_abort_get(pool), > + allocator); > + if (stat != APR_SUCCESS) { > + apr_allocator_destroy(allocator); > + return stat; > + } > + apr_allocator_owner_set(allocator, (*new)->pool); > > (*new)->data = data; > (*new)->func = func; > - > (*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; > + (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t)); > + if ((*new)->td == NULL) { > + apr_pool_destroy((*new)->pool); > + return APR_ENOMEM; > } > > if (attr) > @@ -209,16 +196,15 @@ APR_DECLARE(apr_status_t) apr_thread_cre > else > temp = NULL; > > - if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == > 0) { > - return APR_SUCCESS; > - } > - else { > + if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new)))) { > #ifdef HAVE_ZOS_PTHREADS > stat = errno; > #endif > - > + apr_pool_destroy((*new)->pool); > return stat; > } > + > + return APR_SUCCESS; > } > > APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) > @@ -280,8 +266,6 @@ APR_DECLARE(apr_status_t) apr_thread_det > #else > if ((stat = pthread_detach(*thd->td)) == 0) { > #endif > - /* Detach from the parent pool too */ > - apr__pool_unmanage(thd->pool); > thd->detached = 1; > > return APR_SUCCESS; > > Modified: apr/apr/branches/1.7.x/threadproc/win32/thread.c > URL: > http://svn.apache.org/viewvc/apr/apr/branches/1.7.x/threadproc/win32/thread.c?rev=1897210&r1=1897209&r2=1897210&view=diff > ============================================================================== > --- apr/apr/branches/1.7.x/threadproc/win32/thread.c (original) > +++ apr/apr/branches/1.7.x/threadproc/win32/thread.c Wed Jan 19 17:06:36 2022 > @@ -28,9 +28,6 @@ > /* 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) > { > @@ -94,45 +91,36 @@ APR_DECLARE(apr_status_t) apr_thread_cre > void *data, apr_pool_t *pool) > { > apr_status_t stat; > - unsigned temp; > + unsigned temp; > HANDLE handle; > - > + apr_allocator_t *allocator; > + > (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); > - > if ((*new) == NULL) { > return APR_ENOMEM; > } > > - (*new)->data = data; > - (*new)->func = func; > - > - 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); > - } > + /* The thread can be detached anytime (from the creation or later with > + * apr_thread_detach), so it needs its own pool and allocator to not > + * depend on a 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. > + */ > + stat = apr_allocator_create(&allocator); > + if (stat != APR_SUCCESS) { > + return stat; > } > + stat = apr_pool_create_unmanaged_ex(&(*new)->pool, > + apr_pool_abort_get(pool), > + allocator); > if (stat != APR_SUCCESS) { > + apr_allocator_destroy(allocator); > return stat; > } > + apr_allocator_owner_set(allocator, (*new)->pool); > + > + (*new)->data = data; > + (*new)->func = func; > > /* Use 0 for default Thread Stack Size, because that will > * default the stack to the same size as the calling thread. > @@ -142,7 +130,9 @@ APR_DECLARE(apr_status_t) apr_thread_cre > (DWORD) (attr ? attr->stacksize : 0), > (unsigned int (APR_THREAD_FUNC *)(void > *))dummy_worker, > (*new), 0, &temp)) == 0) { > - return APR_FROM_OS_ERROR(_doserrno); > + stat = APR_FROM_OS_ERROR(_doserrno); > + apr_pool_destroy((*new)->pool); > + return stat; > } > #else > if ((handle = CreateThread(NULL, > @@ -155,8 +145,9 @@ APR_DECLARE(apr_status_t) apr_thread_cre > if (attr && attr->detach) { > CloseHandle(handle); > } > - else > + else { > (*new)->td = handle; > + } > > return APR_SUCCESS; > } > @@ -215,8 +206,6 @@ APR_DECLARE(apr_status_t) apr_thread_det > } > > if (CloseHandle(thd->td)) { > - /* Detach from the parent pool too */ > - apr__pool_unmanage(thd->pool); > thd->td = NULL; > return APR_SUCCESS; > } > >