Bug 988464: log nsThreads still active at nsThreadManager::Shutdown() r=bsmedberg

This commit is contained in:
Randell Jesup 2014-07-17 00:38:51 -04:00
parent 229a6bf2e3
commit 7385a3fcfb
4 changed files with 62 additions and 12 deletions

View File

@ -518,7 +518,7 @@ class Automation(object):
env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
# Set WebRTC logging in case it is not set yet
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,nsThreadManager:5')
env.setdefault('R_LOG_LEVEL', '6')
env.setdefault('R_LOG_DESTINATION', 'stderr')
env.setdefault('R_LOG_VERBOSE', '1')

View File

@ -498,7 +498,7 @@ def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=N
env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
# Set WebRTC logging in case it is not set yet
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,nsThreadManager:5')
env.setdefault('R_LOG_LEVEL', '6')
env.setdefault('R_LOG_DESTINATION', 'stderr')
env.setdefault('R_LOG_VERBOSE', '1')

View File

@ -74,6 +74,7 @@ protected:
friend class nsNestedEventTarget;
friend class nsThreadShutdownEvent;
friend class nsThreadManager;
virtual ~nsThread();
@ -156,11 +157,12 @@ protected:
}
};
// This lock protects access to mObserver, mEvents and mEventsAreDoomed.
// All of those fields are only modified on the thread itself (never from
// another thread). This means that we can avoid holding the lock while
// using mObserver and mEvents on the thread itself. When calling PutEvent
// on mEvents, we have to hold the lock to synchronize with PopEventQueue.
// This lock protects access to mObserver, mEvents and mEventsAreDoomed
// and mShutdownRequired. All of those fields (except mShutdownRequired)
// are only modified on the thread itself (never from another thread).
// This means that we can avoid holding the lock while using mObserver
// and mEvents on the thread itself. When calling PutEvent on mEvents,
// we have to hold the lock to synchronize with PopEventQueue.
mozilla::Mutex mLock;
nsCOMPtr<nsIThreadObserver> mObserver;

View File

@ -18,6 +18,21 @@
using namespace mozilla;
#ifdef PR_LOGGING
static PRLogModuleInfo *
GetThreadManagerLog()
{
static PRLogModuleInfo *sLog;
if (!sLog)
sLog = PR_NewLogModule("nsThreadManager");
return sLog;
}
#endif
#ifdef LOG
#undef LOG
#endif
#define LOG(args) PR_LOG(GetThreadManagerLog(), PR_LOG_DEBUG, args)
#ifdef XP_WIN
#include <windows.h>
DWORD gTLSThreadIDIndex = TlsAlloc();
@ -163,12 +178,45 @@ nsThreadManager::Shutdown()
// to shutdown. This means that we have to preserve a mostly functioning
// world until such time as the threads exit.
// Shutdown all threads that require it (join with threads that we created).
for (uint32_t i = 0; i < threads.Length(); ++i) {
nsThread* thread = threads[i];
if (thread->ShutdownRequired()) {
thread->Shutdown();
{
#ifdef PR_LOGGING
// don't encourage other threads to run here by dumping log messages...
char buffer[4096];
char *ptr = buffer;
uint32_t leaked = 0;
for (uint32_t i = 0; i < threads.Length(); ++i) {
nsThread *thread = threads[i];
if (thread->ShutdownRequired()) {
leaked++;
}
}
if (leaked > 0) {
PR_snprintf(ptr, sizeof(buffer), "*** %u threads active at %s\n", leaked, __FUNCTION__);
ptr += strlen(ptr);
}
#endif
for (uint32_t i = 0; i < threads.Length(); ++i) {
nsThread *thread = threads[i];
#ifdef PR_LOGGING
{
// So the PRThread can't go away while we're getting the name!
MutexAutoLock lock(thread->mLock);
if (thread->ShutdownRequired()) {
PRThread * prThread = thread->GetPRThread();
const char * name = PR_GetThreadName(prThread);
PR_snprintf(ptr, sizeof(buffer), "Thread %s (%p) still active\n", name ? name : "<unnamed>", thread);
ptr += strlen(ptr);
}
}
#endif
if (thread->ShutdownRequired()) {
thread->Shutdown();
}
}
#ifdef PR_LOGGING
LOG(("%s", buffer));
#endif
}
// In case there are any more events somehow...