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 2020/12/03 20:19:40 UTC

svn commit: r1884077 - in /apr/apr/trunk: include/arch/beos/ include/arch/netware/ include/arch/unix/ include/arch/win32/ threadproc/beos/ threadproc/netware/ threadproc/os2/ threadproc/unix/ threadproc/win32/

Author: ylavic
Date: Thu Dec  3 20:19:40 2020
New Revision: 1884077

URL: http://svn.apache.org/viewvc?rev=1884077&view=rev
Log:
apr_thread: destroy the thread's pool at join() time, unless detached.

Destroying a joinable thread pool from apr_thread_exit() or when the thread
function returns (i.e. from inside the thread itself) is racy, or deadlocky
with APR_POOL_DEBUG, with the parent pool is being destroyed.

This commit adds a ->detached flag in each arch's apr_thread_t struct to track
whether a thread is detached (either at _create() or _detach() time). If
detached, it's pool is destroyed when the thread exits, otherwise when the
thread is joined with apr_thread_join().

Modified:
    apr/apr/trunk/include/arch/beos/apr_arch_threadproc.h
    apr/apr/trunk/include/arch/netware/apr_arch_threadproc.h
    apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h
    apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h
    apr/apr/trunk/threadproc/beos/thread.c
    apr/apr/trunk/threadproc/netware/thread.c
    apr/apr/trunk/threadproc/os2/thread.c
    apr/apr/trunk/threadproc/unix/thread.c
    apr/apr/trunk/threadproc/win32/thread.c

Modified: apr/apr/trunk/include/arch/beos/apr_arch_threadproc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/beos/apr_arch_threadproc.h?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/beos/apr_arch_threadproc.h (original)
+++ apr/apr/trunk/include/arch/beos/apr_arch_threadproc.h Thu Dec  3 20:19:40 2020
@@ -45,6 +45,7 @@ struct apr_thread_t {
     void *data;
     apr_thread_start_t func;
     apr_status_t exitval;
+    int detached;
 };
 
 struct apr_threadattr_t {

Modified: apr/apr/trunk/include/arch/netware/apr_arch_threadproc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/netware/apr_arch_threadproc.h?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/netware/apr_arch_threadproc.h (original)
+++ apr/apr/trunk/include/arch/netware/apr_arch_threadproc.h Thu Dec  3 20:19:40 2020
@@ -36,6 +36,7 @@ struct apr_thread_t {
     void *data;
     apr_thread_start_t func;
     apr_status_t exitval;
+    int detached;
 };
 
 struct apr_threadattr_t {

Modified: apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h (original)
+++ apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h Thu Dec  3 20:19:40 2020
@@ -59,6 +59,7 @@ struct apr_thread_t {
     void *data;
     apr_thread_start_t func;
     apr_status_t exitval;
+    int detached;
 };
 
 struct apr_threadattr_t {

Modified: apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h (original)
+++ apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h Thu Dec  3 20:19:40 2020
@@ -31,6 +31,7 @@ struct apr_thread_t {
     void *data;
     apr_thread_start_t func;
     apr_status_t exitval;
+    int exited;
 };
 
 struct apr_threadattr_t {

Modified: apr/apr/trunk/threadproc/beos/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/beos/thread.c?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/beos/thread.c (original)
+++ apr/apr/trunk/threadproc/beos/thread.c Thu Dec  3 20:19:40 2020
@@ -69,7 +69,9 @@ static void *dummy_worker(void *opaque)
 
     apr_pool_owner_set(thd->pool, 0);
     ret = thd->func(thd, thd->data);
-    apr_pool_destroy(thd->pool);
+    if (thd->detached) {
+        apr_pool_destroy(thd->pool);
+    }
     return ret;
 }
 
@@ -80,7 +82,7 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     int32 temp;
     apr_status_t stat;
     
-    (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+    (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
     if ((*new) == NULL) {
         return APR_ENOMEM;
     }
@@ -88,6 +90,7 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     (*new)->data = data;
     (*new)->func = func;
     (*new)->exitval = -1;
+    (*new)->detached = (attr && apr_threadattr_detach_get(attr) == APR_DETACH);
 
     /* First we create the new thread...*/
 	if (attr)
@@ -126,14 +129,21 @@ int apr_os_thread_equal(apr_os_thread_t
 
 APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
 {
-    apr_pool_destroy(thd->pool);
     thd->exitval = retval;
+    if (thd->detached) {
+        apr_pool_destroy(thd->pool);
+    }
     exit_thread ((status_t)(retval));
 }
 
 APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
 {
     status_t rv = 0, ret;
+
+    if (thd->detached) {
+        return APR_EINVAL;
+    }
+
     ret = wait_for_thread(thd->td, &rv);
     if (ret == B_NO_ERROR) {
         *retval = rv;
@@ -145,6 +155,7 @@ APR_DECLARE(apr_status_t) apr_thread_joi
          */
         if (thd->exitval != -1) {
             *retval = thd->exitval;
+            apr_pool_destroy(thd->pool);
             return APR_SUCCESS;
         } else 
             return ret;
@@ -153,7 +164,12 @@ APR_DECLARE(apr_status_t) apr_thread_joi
 
 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
-	if (suspend_thread(thd->td) == B_NO_ERROR){
+    if (thd->detached) {
+        return APR_EINVAL;
+    }
+
+    if (suspend_thread(thd->td) == B_NO_ERROR) {
+        thd->detached = 1;
         return APR_SUCCESS;
     }
     else {

Modified: apr/apr/trunk/threadproc/netware/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/netware/thread.c?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/netware/thread.c (original)
+++ apr/apr/trunk/threadproc/netware/thread.c Thu Dec  3 20:19:40 2020
@@ -71,7 +71,9 @@ static void *dummy_worker(void *opaque)
 
     apr_pool_owner_set(thd->pool, 0);
     ret = thd->func(thd, thd->data);
-    apr_pool_destroy(thd->pool);
+    if (thd->detached) {
+        apr_pool_destroy(thd->pool);
+    }
     return ret;
 }
 
@@ -102,7 +104,7 @@ apr_status_t apr_thread_create(apr_threa
         stack_size = attr->stack_size;
     }
     
-    (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+    (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
@@ -111,6 +113,7 @@ apr_status_t apr_thread_create(apr_threa
     (*new)->data = data;
     (*new)->func = func;
     (*new)->thread_name = (char*)apr_pstrdup(pool, threadName);
+    (*new)->detached = (attr && apr_threadattr_detach_get(attr) == APR_DETACH);
     
     stat = apr_pool_create(&(*new)->pool, pool);
     if (stat != APR_SUCCESS) {
@@ -162,7 +165,9 @@ void apr_thread_yield()
 void apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
 {
     thd->exitval = retval;
-    apr_pool_destroy(thd->pool);
+    if (thd->detached) {
+        apr_pool_destroy(thd->pool);
+    }
     NXThreadExit(NULL);
 }
 
@@ -172,8 +177,13 @@ apr_status_t apr_thread_join(apr_status_
     apr_status_t  stat;    
     NXThreadId_t dthr;
 
+    if (thd->detached) {
+        return APR_EINVAL;
+    }
+
     if ((stat = NXThreadJoin(thd->td, &dthr, NULL)) == 0) {
         *retval = thd->exitval;
+        apr_pool_destroy(thd->pool);
         return APR_SUCCESS;
     }
     else {
@@ -183,6 +193,11 @@ apr_status_t apr_thread_join(apr_status_
 
 apr_status_t apr_thread_detach(apr_thread_t *thd)
 {
+    if (thd->detached) {
+        return APR_EINVAL;
+    }
+
+    thd->detached = 1;
     return APR_SUCCESS;
 }
 

Modified: apr/apr/trunk/threadproc/os2/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/os2/thread.c?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/os2/thread.c (original)
+++ apr/apr/trunk/threadproc/os2/thread.c Thu Dec  3 20:19:40 2020
@@ -71,7 +71,9 @@ static void apr_thread_begin(void *arg)
   apr_thread_t *thread = (apr_thread_t *)arg;
   apr_pool_owner_set(thread->pool, 0);
   thread->exitval = thread->func(thread, thread->data);
-  apr_pool_destroy(thread->pool);
+  if (thd->attr->attr & APR_THREADATTR_DETACHED) {
+      apr_pool_destroy(thread->pool);
+  }
 }
 
 
@@ -83,7 +85,7 @@ APR_DECLARE(apr_status_t) apr_thread_cre
     apr_status_t stat;
     apr_thread_t *thread;
  
-    thread = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+    thread = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
     *new = thread;
 
     if (thread == NULL) {
@@ -134,7 +136,9 @@ APR_DECLARE(apr_os_thread_t) apr_os_thre
 APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
 {
     thd->exitval = retval;
-    apr_pool_destroy(thd->pool);
+    if (thd->attr->attr & APR_THREADATTR_DETACHED) {
+        apr_pool_destroy(thd->pool);
+    }
     _endthread();
 }
 
@@ -154,6 +158,9 @@ APR_DECLARE(apr_status_t) apr_thread_joi
         rc = 0; /* Thread had already terminated */
 
     *retval = thd->exitval;
+    if (rc == 0) {
+        apr_pool_destroy(thd->pool);
+    }
     return APR_FROM_OS_ERROR(rc);
 }
 
@@ -161,6 +168,10 @@ APR_DECLARE(apr_status_t) apr_thread_joi
 
 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
+    if (thd->attr->attr & APR_THREADATTR_DETACHED) {
+        return APR_EINVAL;
+    }
+
     thd->attr->attr |= APR_THREADATTR_DETACHED;
     return APR_SUCCESS;
 }

Modified: apr/apr/trunk/threadproc/unix/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/unix/thread.c?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/unix/thread.c (original)
+++ apr/apr/trunk/threadproc/unix/thread.c Thu Dec  3 20:19:40 2020
@@ -143,7 +143,9 @@ static void *dummy_worker(void *opaque)
 
     apr_pool_owner_set(thread->pool, 0);
     ret = thread->func(thread, thread->data);
-    apr_pool_destroy(thread->pool);
+    if (thread->detached) {
+        apr_pool_destroy(thread->pool);
+    }
     return ret;
 }
 
@@ -170,17 +172,17 @@ APR_DECLARE(apr_status_t) apr_thread_cre
 
     (*new)->data = data;
     (*new)->func = func;
+    (*new)->detached = (attr && apr_threadattr_detach_get(attr) == APR_DETACH);
+    stat = apr_pool_create(&(*new)->pool, pool);
+    if (stat != APR_SUCCESS) {
+        return stat;
+    }
 
     if (attr)
         temp = &attr->attr;
     else
         temp = NULL;
 
-    stat = apr_pool_create(&(*new)->pool, pool);
-    if (stat != APR_SUCCESS) {
-        return stat;
-    }
-
     if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) {
         return APR_SUCCESS;
     }
@@ -208,7 +210,9 @@ APR_DECLARE(void) apr_thread_exit(apr_th
                                   apr_status_t retval)
 {
     thd->exitval = retval;
-    apr_pool_destroy(thd->pool);
+    if (thd->detached) {
+        apr_pool_destroy(thd->pool);
+    }
     pthread_exit(NULL);
 }
 
@@ -218,8 +222,13 @@ APR_DECLARE(apr_status_t) apr_thread_joi
     apr_status_t stat;
     apr_status_t *thread_stat;
 
+    if (thd->detached) {
+        return APR_EINVAL;
+    }
+
     if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) {
         *retval = thd->exitval;
+        apr_pool_destroy(thd->pool);
         return APR_SUCCESS;
     }
     else {
@@ -235,11 +244,16 @@ APR_DECLARE(apr_status_t) apr_thread_det
 {
     apr_status_t stat;
 
+    if (thd->detached) {
+        return APR_EINVAL;
+    }
+
 #ifdef HAVE_ZOS_PTHREADS
     if ((stat = pthread_detach(thd->td)) == 0) {
 #else
     if ((stat = pthread_detach(*thd->td)) == 0) {
 #endif
+        thd->detached = 1;
 
         return APR_SUCCESS;
     }

Modified: apr/apr/trunk/threadproc/win32/thread.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/win32/thread.c?rev=1884077&r1=1884076&r2=1884077&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/win32/thread.c (original)
+++ apr/apr/trunk/threadproc/win32/thread.c Thu Dec  3 20:19:40 2020
@@ -80,7 +80,9 @@ static void *dummy_worker(void *opaque)
     TlsSetValue(tls_apr_thread, thd->td);
     apr_pool_owner_set(thd->pool, 0);
     ret = thd->func(thd, thd->data);
-    apr_pool_destroy(thd->pool);
+    if (!thd->td) { /* detached? */
+        apr_pool_destroy(thd->pool);
+    }
     return ret;
 }
 
@@ -93,7 +95,7 @@ APR_DECLARE(apr_status_t) apr_thread_cre
 	unsigned temp;
     HANDLE handle;
 
-    (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
+    (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
 
     if ((*new) == NULL) {
         return APR_ENOMEM;
@@ -101,7 +103,6 @@ APR_DECLARE(apr_status_t) apr_thread_cre
 
     (*new)->data = data;
     (*new)->func = func;
-    (*new)->td   = NULL;
     stat = apr_pool_create(&(*new)->pool, pool);
     if (stat != APR_SUCCESS) {
         return stat;
@@ -136,9 +137,11 @@ APR_DECLARE(apr_status_t) apr_thread_cre
 
 APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
 {
+    thd->exited = 1;
     thd->exitval = retval;
-    apr_pool_destroy(thd->pool);
-    thd->pool = NULL;
+    if (!thd->td) { /* detached? */
+        apr_pool_destroy(thd->pool);
+    }
 #ifndef _WIN32_WCE
     _endthreadex(0);
 #else
@@ -150,30 +153,40 @@ APR_DECLARE(apr_status_t) apr_thread_joi
                                           apr_thread_t *thd)
 {
     apr_status_t rv = APR_SUCCESS;
+    DWORD ret;
     
     if (!thd->td) {
         /* Can not join on detached threads */
         return APR_DETACH;
     }
-    rv = WaitForSingleObject(thd->td, INFINITE);
-    if ( rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+
+    ret = WaitForSingleObject(thd->td, INFINITE);
+    if (ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED) {
         /* If the thread_exit has been called */
-        if (!thd->pool)
+        if (thd->exited)
             *retval = thd->exitval;
         else
             rv = APR_INCOMPLETE;
     }
     else
         rv = apr_get_os_error();
-    CloseHandle(thd->td);
-    thd->td = NULL;
+
+    if (rv == APR_SUCCESS) {
+        CloseHandle(thd->td);
+        apr_pool_destroy(thd->pool);
+        thd->td = NULL;
+    }
 
     return rv;
 }
 
 APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
 {
-    if (thd->td && CloseHandle(thd->td)) {
+    if (!thd->td) {
+        return APR_EINVAL;
+    }
+
+    if (CloseHandle(thd->td)) {
         thd->td = NULL;
         return APR_SUCCESS;
     }