--- a/nsprpub/pr/src/pthreads/ptthread.c
+++ b/nsprpub/pr/src/pthreads/ptthread.c
@@ -15,16 +15,18 @@
#include "primpl.h"
#include "prpdce.h"
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <dlfcn.h>
+#include <execinfo.h>
+#include <stdio.h>
#if defined(OPENBSD) || defined(FREEBSD) || defined(DRAGONFLY)
#include <pthread_np.h>
#endif
#ifdef SYMBIAN
/* In Open C sched_get_priority_min/max do not work properly, so we undefine
* _POSIX_THREAD_PRIORITY_SCHEDULING here.
@@ -284,17 +286,34 @@ static PRThread* pt_AttachThread(void)
thred->priority = PR_PRIORITY_NORMAL;
thred->id = pthread_self();
thred->idSet = PR_TRUE;
#ifdef _PR_NICE_PRIORITY_SCHEDULING
thred->tid = gettid();
#endif
rv = pthread_setspecific(pt_book.key, thred);
- PR_ASSERT(0 == rv);
+ /* Expand PR_ASSERT(0 == rv) to debug Bug 1399746. */
+#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
+ if (0 != rv) {
+ void* callstack[128];
+ int i, frames = backtrace(callstack, 128);
+ char** strs = backtrace_symbols(callstack, frames);
+ char msg[128];
+ snprintf(msg, sizeof(msg), "0 == rv (%d), pt_book.keyCreated=%d",
+ rv, (int)pt_book.keyCreated);
+ /* PR_Assert(msg, __FILE__, __LINE__); */
+ fprintf(stderr, "Assertion failure: %s, at %s:%d\n", msg, __FILE__, __LINE__);
+ for (i = 0; i < frames; ++i) {
+ fprintf(stderr, "%s\n", strs[i]);
+ }
+ fflush(stderr);
+ free(strs);
+ }
+#endif /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */
thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN;
PR_Lock(pt_book.ml);
/* then put it into the list */
thred->prev = pt_book.last;
if (pt_book.last)
pt_book.last->next = thred;
@@ -1061,16 +1080,23 @@ void PR_HPUX10xInit(shl_t handle, int lo
#elif defined(AIX)
/* Need to use the -binitfini::_PR_Fini linker option. */
#endif
void _PR_Fini(void)
{
void *thred;
int rv;
+ void* callstack[128]; int i, frames = backtrace(callstack, 128);
+ char** strs = backtrace_symbols(callstack, frames);
+ fprintf(stderr, "_PR_Fini called\n");
+ for (i = 0; i < frames; ++i) {
+ fprintf(stderr, "%s\n", strs[i]);
+ }
+ fflush(stderr);
if (!_pr_initialized) {
/* Either NSPR was never successfully initialized or
* PR_Cleanup has been called already. */
if (pt_book.keyCreated)
{
rv = pthread_key_delete(pt_book.key);
PR_ASSERT(0 == rv);
@@ -1096,16 +1122,18 @@ void _PR_Fini(void)
/* TODO: free other resources used by NSPR */
/* _pr_initialized = PR_FALSE; */
} /* _PR_Fini */
PR_IMPLEMENT(PRStatus) PR_Cleanup(void)
{
PRThread *me = PR_GetCurrentThread();
int rv;
+ fprintf(stderr, "PR_Cleanup called\n");
+ fflush(stderr);
PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
PR_ASSERT(me->state & PT_THREAD_PRIMORD);
if (me->state & PT_THREAD_PRIMORD)
{
PR_Lock(pt_book.ml);
while (pt_book.user > pt_book.this_many)
PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
if (me->state & PT_THREAD_SYSTEM)