mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 988464: log nsThreads still active at nsThreadManager::Shutdown() r=bsmedberg
This commit is contained in:
parent
229a6bf2e3
commit
7385a3fcfb
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -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;
|
||||
|
@ -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...
|
||||
|
Loading…
Reference in New Issue
Block a user