Bug 383977, Crash on exit caused by thread local storage cleanup [@ PL_DHashTableOperate] MOZILLA_1_9a7_RC1 MOZILLA_1_9a7_RELEASE NSPR_HEAD_20070713 WEB_CONTENT_HANDLING_20070621_POSTMERGE_20070719_FIXED WEB_CONTENT_HANDLING_20070621_POST_HANDLER_SERVICE_20070720
authorkaie%kuix.de
Sat, 07 Jul 2007 01:01:42 +0000
changeset 3849 512b34c94c294619af01ccc58d008695ed2addcf
parent 3848 e767d8d1efc59c5ef5b79681399a8e8d05ff5700
child 3851 ebeb2c3a63b9e387bcfe4a36814bda340e9bfec3
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)