Bug 383977, Crash on exit caused by thread local storage cleanup [@ PL_DHashTableOperate] NSPRPUB_PRE_4_2_CLIENT_BRANCH UPDATE_PACKAGING_R1 UPDATE_PACKAGING_R10 UPDATE_PACKAGING_R11 UPDATE_PACKAGING_R11_1 UPDATE_PACKAGING_R12 UPDATE_PACKAGING_R13 UPDATE_PACKAGING_R14 UPDATE_PACKAGING_R2 UPDATE_PACKAGING_R3 UPDATE_PACKAGING_R4 UPDATE_PACKAGING_R5 UPDATE_PACKAGING_R6 UPDATE_PACKAGING_R7 UPDATE_PACKAGING_R8 UPDATE_PACKAGING_R9 WEB_CONTENT_HANDLING_20070621_PREMERGE_20070719
authorkaie%kuix.de
Sat, 07 Jul 2007 01:02:16 +0000
branchNSPRPUB_PRE_4_2_CLIENT_BRANCH
changeset 3850 4c8109e865dc
parent 3844 e290783d4531
push idunknown
push userunknown
push dateunknown
bugs383977
Bug 383977, Crash on exit caused by thread local storage cleanup [@ PL_DHashTableOperate] r=wtc
pr/src/pthreads/ptthread.c
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -70,16 +70,17 @@ static struct _PT_Bookeeping
     pthread_key_t key;          /* private private data key */
     PRThread *first, *last;     /* list of threads we know about */
 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
     PRInt32 minPrio, maxPrio;   /* range of scheduling priorities */
 #endif
 } pt_book = {0};
 
 static void _pt_thread_death(void *arg);
+static void _pt_thread_death_internal(void *arg, PRBool callDestructors);
 static void init_pthread_gc_support(void);
 
 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
 static PRIntn pt_PriorityMap(PRThreadPriority pri)
 {
 #ifdef NTO
     /* This priority algorithm causes lots of problems on Neutrino
      * for now I have just hard coded everything to run at priority 10
@@ -802,32 +803,39 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRInterv
         PR_Unlock(_pr_sleeplock);
         PR_DestroyCondVar(cv);
     }
     return rv;
 }  /* PR_Sleep */
 
 static void _pt_thread_death(void *arg)
 {
+    /* PR_TRUE for: call destructors */ 
+    _pt_thread_death_internal(arg, PR_TRUE);
+}
+
+static void _pt_thread_death_internal(void *arg, PRBool callDestructors)
+{
     PRThread *thred = (PRThread*)arg;
 
     if (thred->state & (PT_THREAD_FOREIGN|PT_THREAD_PRIMORD))
     {
         PR_Lock(pt_book.ml);
         if (NULL == thred->prev)
             pt_book.first = thred->next;
         else
             thred->prev->next = thred->next;
         if (NULL == thred->next)
             pt_book.last = thred->prev;
         else
             thred->next->prev = thred->prev;
         PR_Unlock(pt_book.ml);
     }
-    _PR_DestroyThreadPrivate(thred);
+    if (callDestructors)
+        _PR_DestroyThreadPrivate(thred);
     PR_Free(thred->privateData);
     if (NULL != thred->errorString)
         PR_Free(thred->errorString);
     PR_Free(thred->stack);
     if (NULL != thred->syspoll_list)
         PR_Free(thred->syspoll_list);
 #if defined(_PR_POLL_WITH_SELECT)
     if (NULL != thred->selectfd_list)
@@ -991,17 +999,21 @@ void _PR_Fini(void)
     void *thred;
     int rv;
 
     if (!_pr_initialized) return;
 
     _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
     if (NULL != thred)
     {
-        _pt_thread_death(thred);
+        /*
+         * PR_FALSE, because it is unsafe to call back to the 
+         * thread private data destructors at final cleanup.
+         */
+        _pt_thread_death_internal(thred, PR_FALSE);
         rv = pthread_setspecific(pt_book.key, NULL);
         PR_ASSERT(0 == rv);
     }
     /* TODO: free other resources used by NSPR */
     /* _pr_initialized = PR_FALSE; */
 }  /* _PR_Fini */
 
 PR_IMPLEMENT(PRStatus) PR_Cleanup(void)