From 51e89c24b2f7cdf989faf1561089c2ced77fa0a7 Mon Sep 17 00:00:00 2001 From: "nisheeth%netscape.com" Date: Fri, 19 Nov 1999 03:50:28 +0000 Subject: [PATCH] r=harishd. - The stack walking code now works on windows. We were initializing the symbol handler on each DLL load which was resetting its symbol tables. Now, we don't re-init the symbol handler repeatedly. - Added support for an environment variable, XPCOM_REFCNT_LOG_ENABLE_VIA_PREF. When this is set to 1, refcount logging is done based on whether the "Enable XPCOM refcount log" pref in the Debug pane is set. If this is not set, refcount logging is not affected by the pref. git-svn-id: svn://10.0.0.236/trunk@53963 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/suite/common/pref/pref-debug.xul | 6 +- mozilla/suite/debugQA/content/pref-debug.xul | 6 +- .../debugQA/locales/en-US/pref-debug.dtd | 3 +- .../en-US/chrome/common/pref/pref-debug.dtd | 3 +- mozilla/xpcom/base/nsTraceRefcnt.cpp | 107 ++++++++++++++---- mozilla/xpcom/base/nsTraceRefcnt.h | 2 + mozilla/xpcom/base/nsTraceRefcntImpl.cpp | 107 ++++++++++++++---- mozilla/xpcom/base/nsTraceRefcntImpl.h | 2 + .../resources/content/pref-debug.xul | 6 +- .../resources/locale/en-US/pref-debug.dtd | 3 +- 10 files changed, 199 insertions(+), 46 deletions(-) diff --git a/mozilla/suite/common/pref/pref-debug.xul b/mozilla/suite/common/pref/pref-debug.xul index 9d827a51c1f..ed1591ccd42 100644 --- a/mozilla/suite/common/pref/pref-debug.xul +++ b/mozilla/suite/common/pref/pref-debug.xul @@ -144,9 +144,13 @@ &debugDisableXULCache.label; + + + &debugEnableXPCOMRefcntLog.label; + - + diff --git a/mozilla/suite/debugQA/content/pref-debug.xul b/mozilla/suite/debugQA/content/pref-debug.xul index 9d827a51c1f..ed1591ccd42 100644 --- a/mozilla/suite/debugQA/content/pref-debug.xul +++ b/mozilla/suite/debugQA/content/pref-debug.xul @@ -144,9 +144,13 @@ &debugDisableXULCache.label; + + + &debugEnableXPCOMRefcntLog.label; + - + diff --git a/mozilla/suite/debugQA/locales/en-US/pref-debug.dtd b/mozilla/suite/debugQA/locales/en-US/pref-debug.dtd index 5b2000749cb..94f207e43b7 100644 --- a/mozilla/suite/debugQA/locales/en-US/pref-debug.dtd +++ b/mozilla/suite/debugQA/locales/en-US/pref-debug.dtd @@ -23,5 +23,6 @@ - + + diff --git a/mozilla/suite/locales/en-US/chrome/common/pref/pref-debug.dtd b/mozilla/suite/locales/en-US/chrome/common/pref/pref-debug.dtd index 5b2000749cb..94f207e43b7 100644 --- a/mozilla/suite/locales/en-US/chrome/common/pref/pref-debug.dtd +++ b/mozilla/suite/locales/en-US/chrome/common/pref/pref-debug.dtd @@ -23,5 +23,6 @@ - + + diff --git a/mozilla/xpcom/base/nsTraceRefcnt.cpp b/mozilla/xpcom/base/nsTraceRefcnt.cpp index d3e08afff0b..e1643bee6f3 100644 --- a/mozilla/xpcom/base/nsTraceRefcnt.cpp +++ b/mozilla/xpcom/base/nsTraceRefcnt.cpp @@ -54,6 +54,9 @@ #ifdef NS_BUILD_REFCNT_LOGGING #include "plhash.h" #include +#include "nsIPref.h" +#include "nsIServiceManager.h" + #if defined(NS_MT_SUPPORTED) #include "prlock.h" @@ -76,6 +79,9 @@ static PRInt32 gNextSerialNumber; static PRBool gLogging; static PRBool gLogToLeaky; static PRBool gLogLeaksOnly; +static PRBool gEnableViaPref; +static PRBool gRefcountPrefEnabled = PR_FALSE; +static const char* kRefcountPref = "nglayout.debug.enable_xpcom_refcnt_log"; static void (*leakyLogAddRef)(void* p, int oldrc, int newrc); static void (*leakyLogRelease)(void* p, int oldrc, int newrc); @@ -86,6 +92,8 @@ static FILE *gRefcntsLog = nsnull; static FILE *gAllocLog = nsnull; static FILE *gLeakyLog = nsnull; +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); + #define XPCOM_REFCNT_TRACK_BLOAT 0x1 #define XPCOM_REFCNT_LOG_ALL 0x2 #define XPCOM_REFCNT_LOG_SOME 0x4 @@ -572,6 +580,8 @@ static void InitTraceLog(void) PL_CompareValues, PL_CompareValues, NULL, NULL); + + } const char* objects = getenv("XPCOM_MEM_LOG_OBJECTS"); @@ -612,15 +622,27 @@ static void InitTraceLog(void) } } + if (gBloatLog || gRefcntsLog || gAllocLog || gLeakyLog) { gLogging = PR_TRUE; } + const char* s = getenv("XPCOM_REFCNT_LOG_ENABLE_VIA_PREF"); + if (s && strchr(s, '1') >= 0) { + gEnableViaPref = PR_TRUE; + if (gLogging) + printf("### XPCOM_REFCNT_LOG_ENABLE_VIA_PREF defined: Logging will be enabled based on the pref selected in the Debug pane\n"); + } + else + gEnableViaPref = PR_FALSE; + + #if defined(NS_MT_SUPPORTED) gTraceLock = PR_NewLock(); #endif /* NS_MT_SUPPORTED */ } + #endif #if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code @@ -659,11 +681,13 @@ static SYMGETMODULEBASEPROC _SymGetModuleBase; typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL); static SYMGETSYMFROMADDRPROC _SymGetSymFromAddr; +typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD); +static SYMLOADMODULE _SymLoadModule; static PRBool -EnsureSymInitialized() +EnsureImageHlpInitialized() { - PRBool gInitialized = PR_FALSE; + static PRBool gInitialized = PR_FALSE; if (! gInitialized) { HMODULE module = ::LoadLibrary("IMAGEHLP.DLL"); @@ -687,12 +711,27 @@ EnsureSymInitialized() _SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr"); if (!_SymGetSymFromAddr) return PR_FALSE; - gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE); + _SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule"); + if (!_SymLoadModule) return PR_FALSE; + + gInitialized = PR_TRUE; } return gInitialized; -} +} +static PRBool +EnsureSymInitialized() +{ + static PRBool gInitialized = PR_FALSE; + + if (! gInitialized) { + if (! EnsureImageHlpInitialized()) + return PR_FALSE; + gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE); + } + return gInitialized; +} /** * Walk the stack, translating PC's found into strings and recording the * chain in aBuffer. For this to work properly, the dll's must be rebased @@ -710,7 +749,6 @@ nsTraceRefcnt::WalkTheStack(FILE* aStream) { HANDLE myProcess = ::GetCurrentProcess(); HANDLE myThread = ::GetCurrentThread(); - BOOL ok; ok = EnsureSymInitialized(); @@ -762,8 +800,8 @@ nsTraceRefcnt::WalkTheStack(FILE* aStream) 0, NULL ); - fprintf(stdout, "### ERROR: WalkStack: %s", lpMsgBuf); - fflush(stdout); + fprintf(aStream, "### ERROR: WalkStack: %s", lpMsgBuf); + fflush(aStream); LocalFree( lpMsgBuf ); } if (!ok || frame.AddrPC.Offset == 0) @@ -981,6 +1019,30 @@ nsTraceRefcnt::DemangleSymbol(const char * aSymbol, //---------------------------------------------------------------------- + +static int PR_CALLBACK +refcountPrefChanged(const char * newpref, void * data) { + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv); + if (NS_SUCCEEDED(rv) && prefs) { + rv = prefs->GetBoolPref(kRefcountPref, &gRefcountPrefEnabled); + } + return rv; +} + +NS_COM void +nsTraceRefcnt::SetPrefServiceAvailability(PRBool avail) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv); + if (NS_SUCCEEDED(rv) && prefs) { + prefs->GetBoolPref(kRefcountPref, &gRefcountPrefEnabled); + prefs->RegisterCallback(kRefcountPref, refcountPrefChanged, NULL); + } +#endif +} + NS_COM void nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, void* aLibrayHandle) @@ -994,9 +1056,8 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, fprintf(stdout, "### Loading symbols for %s\n", aLibraryName); fflush(stdout); - HANDLE myProcess = ::GetCurrentProcess(); - - BOOL ok = SymInitialize(myProcess, ".;..\\lib", FALSE); + HANDLE myProcess = ::GetCurrentProcess(); + BOOL ok = EnsureSymInitialized(); if (ok) { const char* baseName = aLibraryName; // just get the base name of the library if a full path was given: @@ -1007,7 +1068,7 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, break; } } - DWORD baseAddr = SymLoadModule(myProcess, + DWORD baseAddr = _SymLoadModule(myProcess, NULL, (char*)baseName, (char*)baseName, @@ -1089,11 +1150,14 @@ nsTraceRefcnt::LogAddRef(void* aPtr, if (gLogToLeaky) { (*leakyLogAddRef)(aPtr, aRefCnt - 1, aRefCnt); } - else { - // Can't use PR_LOG(), b/c it truncates the line - fprintf(gRefcntsLog, - "\n<%s> 0x%08X %d AddRef %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); - WalkTheStack(gRefcntsLog); + else { + if (!gEnableViaPref || (gEnableViaPref && gRefcountPrefEnabled)) { + // Can't use PR_LOG(), b/c it truncates the line + fprintf(gRefcntsLog, + "\n<%s> 0x%08X %d AddRef %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); + WalkTheStack(gRefcntsLog); + fflush(gRefcntsLog); + } } } #endif @@ -1137,10 +1201,13 @@ nsTraceRefcnt::LogRelease(void* aPtr, (*leakyLogRelease)(aPtr, aRefCnt + 1, aRefCnt); } else { - // Can't use PR_LOG(), b/c it truncates the line - fprintf(gRefcntsLog, - "\n<%s> 0x%08X %d Release %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); - WalkTheStack(gRefcntsLog); + if (!gEnableViaPref || (gEnableViaPref && gRefcountPrefEnabled)) { + // Can't use PR_LOG(), b/c it truncates the line + fprintf(gRefcntsLog, + "\n<%s> 0x%08X %d Release %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); + WalkTheStack(gRefcntsLog); + fflush(gRefcntsLog); + } } } diff --git a/mozilla/xpcom/base/nsTraceRefcnt.h b/mozilla/xpcom/base/nsTraceRefcnt.h index 579ddf5cfe2..b1343fdb545 100644 --- a/mozilla/xpcom/base/nsTraceRefcnt.h +++ b/mozilla/xpcom/base/nsTraceRefcnt.h @@ -198,6 +198,8 @@ public: int aBufLen); static NS_COM void WalkTheStack(FILE* aStream); + + static NS_COM void SetPrefServiceAvailability(PRBool avail); }; #endif /* nsTraceRefcnt_h___ */ diff --git a/mozilla/xpcom/base/nsTraceRefcntImpl.cpp b/mozilla/xpcom/base/nsTraceRefcntImpl.cpp index d3e08afff0b..e1643bee6f3 100644 --- a/mozilla/xpcom/base/nsTraceRefcntImpl.cpp +++ b/mozilla/xpcom/base/nsTraceRefcntImpl.cpp @@ -54,6 +54,9 @@ #ifdef NS_BUILD_REFCNT_LOGGING #include "plhash.h" #include +#include "nsIPref.h" +#include "nsIServiceManager.h" + #if defined(NS_MT_SUPPORTED) #include "prlock.h" @@ -76,6 +79,9 @@ static PRInt32 gNextSerialNumber; static PRBool gLogging; static PRBool gLogToLeaky; static PRBool gLogLeaksOnly; +static PRBool gEnableViaPref; +static PRBool gRefcountPrefEnabled = PR_FALSE; +static const char* kRefcountPref = "nglayout.debug.enable_xpcom_refcnt_log"; static void (*leakyLogAddRef)(void* p, int oldrc, int newrc); static void (*leakyLogRelease)(void* p, int oldrc, int newrc); @@ -86,6 +92,8 @@ static FILE *gRefcntsLog = nsnull; static FILE *gAllocLog = nsnull; static FILE *gLeakyLog = nsnull; +static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); + #define XPCOM_REFCNT_TRACK_BLOAT 0x1 #define XPCOM_REFCNT_LOG_ALL 0x2 #define XPCOM_REFCNT_LOG_SOME 0x4 @@ -572,6 +580,8 @@ static void InitTraceLog(void) PL_CompareValues, PL_CompareValues, NULL, NULL); + + } const char* objects = getenv("XPCOM_MEM_LOG_OBJECTS"); @@ -612,15 +622,27 @@ static void InitTraceLog(void) } } + if (gBloatLog || gRefcntsLog || gAllocLog || gLeakyLog) { gLogging = PR_TRUE; } + const char* s = getenv("XPCOM_REFCNT_LOG_ENABLE_VIA_PREF"); + if (s && strchr(s, '1') >= 0) { + gEnableViaPref = PR_TRUE; + if (gLogging) + printf("### XPCOM_REFCNT_LOG_ENABLE_VIA_PREF defined: Logging will be enabled based on the pref selected in the Debug pane\n"); + } + else + gEnableViaPref = PR_FALSE; + + #if defined(NS_MT_SUPPORTED) gTraceLock = PR_NewLock(); #endif /* NS_MT_SUPPORTED */ } + #endif #if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code @@ -659,11 +681,13 @@ static SYMGETMODULEBASEPROC _SymGetModuleBase; typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL); static SYMGETSYMFROMADDRPROC _SymGetSymFromAddr; +typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD); +static SYMLOADMODULE _SymLoadModule; static PRBool -EnsureSymInitialized() +EnsureImageHlpInitialized() { - PRBool gInitialized = PR_FALSE; + static PRBool gInitialized = PR_FALSE; if (! gInitialized) { HMODULE module = ::LoadLibrary("IMAGEHLP.DLL"); @@ -687,12 +711,27 @@ EnsureSymInitialized() _SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr"); if (!_SymGetSymFromAddr) return PR_FALSE; - gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE); + _SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule"); + if (!_SymLoadModule) return PR_FALSE; + + gInitialized = PR_TRUE; } return gInitialized; -} +} +static PRBool +EnsureSymInitialized() +{ + static PRBool gInitialized = PR_FALSE; + + if (! gInitialized) { + if (! EnsureImageHlpInitialized()) + return PR_FALSE; + gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE); + } + return gInitialized; +} /** * Walk the stack, translating PC's found into strings and recording the * chain in aBuffer. For this to work properly, the dll's must be rebased @@ -710,7 +749,6 @@ nsTraceRefcnt::WalkTheStack(FILE* aStream) { HANDLE myProcess = ::GetCurrentProcess(); HANDLE myThread = ::GetCurrentThread(); - BOOL ok; ok = EnsureSymInitialized(); @@ -762,8 +800,8 @@ nsTraceRefcnt::WalkTheStack(FILE* aStream) 0, NULL ); - fprintf(stdout, "### ERROR: WalkStack: %s", lpMsgBuf); - fflush(stdout); + fprintf(aStream, "### ERROR: WalkStack: %s", lpMsgBuf); + fflush(aStream); LocalFree( lpMsgBuf ); } if (!ok || frame.AddrPC.Offset == 0) @@ -981,6 +1019,30 @@ nsTraceRefcnt::DemangleSymbol(const char * aSymbol, //---------------------------------------------------------------------- + +static int PR_CALLBACK +refcountPrefChanged(const char * newpref, void * data) { + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv); + if (NS_SUCCEEDED(rv) && prefs) { + rv = prefs->GetBoolPref(kRefcountPref, &gRefcountPrefEnabled); + } + return rv; +} + +NS_COM void +nsTraceRefcnt::SetPrefServiceAvailability(PRBool avail) +{ +#ifdef NS_BUILD_REFCNT_LOGGING + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv); + if (NS_SUCCEEDED(rv) && prefs) { + prefs->GetBoolPref(kRefcountPref, &gRefcountPrefEnabled); + prefs->RegisterCallback(kRefcountPref, refcountPrefChanged, NULL); + } +#endif +} + NS_COM void nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, void* aLibrayHandle) @@ -994,9 +1056,8 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, fprintf(stdout, "### Loading symbols for %s\n", aLibraryName); fflush(stdout); - HANDLE myProcess = ::GetCurrentProcess(); - - BOOL ok = SymInitialize(myProcess, ".;..\\lib", FALSE); + HANDLE myProcess = ::GetCurrentProcess(); + BOOL ok = EnsureSymInitialized(); if (ok) { const char* baseName = aLibraryName; // just get the base name of the library if a full path was given: @@ -1007,7 +1068,7 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName, break; } } - DWORD baseAddr = SymLoadModule(myProcess, + DWORD baseAddr = _SymLoadModule(myProcess, NULL, (char*)baseName, (char*)baseName, @@ -1089,11 +1150,14 @@ nsTraceRefcnt::LogAddRef(void* aPtr, if (gLogToLeaky) { (*leakyLogAddRef)(aPtr, aRefCnt - 1, aRefCnt); } - else { - // Can't use PR_LOG(), b/c it truncates the line - fprintf(gRefcntsLog, - "\n<%s> 0x%08X %d AddRef %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); - WalkTheStack(gRefcntsLog); + else { + if (!gEnableViaPref || (gEnableViaPref && gRefcountPrefEnabled)) { + // Can't use PR_LOG(), b/c it truncates the line + fprintf(gRefcntsLog, + "\n<%s> 0x%08X %d AddRef %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); + WalkTheStack(gRefcntsLog); + fflush(gRefcntsLog); + } } } #endif @@ -1137,10 +1201,13 @@ nsTraceRefcnt::LogRelease(void* aPtr, (*leakyLogRelease)(aPtr, aRefCnt + 1, aRefCnt); } else { - // Can't use PR_LOG(), b/c it truncates the line - fprintf(gRefcntsLog, - "\n<%s> 0x%08X %d Release %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); - WalkTheStack(gRefcntsLog); + if (!gEnableViaPref || (gEnableViaPref && gRefcountPrefEnabled)) { + // Can't use PR_LOG(), b/c it truncates the line + fprintf(gRefcntsLog, + "\n<%s> 0x%08X %d Release %d\n", aClazz, PRInt32(aPtr), serialno, aRefCnt); + WalkTheStack(gRefcntsLog); + fflush(gRefcntsLog); + } } } diff --git a/mozilla/xpcom/base/nsTraceRefcntImpl.h b/mozilla/xpcom/base/nsTraceRefcntImpl.h index 579ddf5cfe2..b1343fdb545 100644 --- a/mozilla/xpcom/base/nsTraceRefcntImpl.h +++ b/mozilla/xpcom/base/nsTraceRefcntImpl.h @@ -198,6 +198,8 @@ public: int aBufLen); static NS_COM void WalkTheStack(FILE* aStream); + + static NS_COM void SetPrefServiceAvailability(PRBool avail); }; #endif /* nsTraceRefcnt_h___ */ diff --git a/mozilla/xpfe/components/prefwindow/resources/content/pref-debug.xul b/mozilla/xpfe/components/prefwindow/resources/content/pref-debug.xul index 9d827a51c1f..ed1591ccd42 100644 --- a/mozilla/xpfe/components/prefwindow/resources/content/pref-debug.xul +++ b/mozilla/xpfe/components/prefwindow/resources/content/pref-debug.xul @@ -144,9 +144,13 @@ &debugDisableXULCache.label; + + + &debugEnableXPCOMRefcntLog.label; + - + diff --git a/mozilla/xpfe/components/prefwindow/resources/locale/en-US/pref-debug.dtd b/mozilla/xpfe/components/prefwindow/resources/locale/en-US/pref-debug.dtd index 5b2000749cb..94f207e43b7 100644 --- a/mozilla/xpfe/components/prefwindow/resources/locale/en-US/pref-debug.dtd +++ b/mozilla/xpfe/components/prefwindow/resources/locale/en-US/pref-debug.dtd @@ -23,5 +23,6 @@ - + +