diff --git a/ipc/glue/ForkServer.cpp b/ipc/glue/ForkServer.cpp index 9733f2d9aabb..5bc2d99abe1c 100644 --- a/ipc/glue/ForkServer.cpp +++ b/ipc/glue/ForkServer.cpp @@ -302,8 +302,10 @@ ForkServer::RunForkServer(int* aArgc, char*** aArgv) { forkserver.mAppProcBuilder->InitAppProcess(aArgc, aArgv); forkserver.mAppProcBuilder.reset(); - // Open log files again with the right names with the new PID. - nsTraceRefcnt::ResetLogFiles(); + MOZ_ASSERT(NS_LITERAL_CSTRING("tab") == (*aArgv)[*aArgc - 1], "Only |tab| is allowed!"); + + // Open log files again with right names and the new PID. + nsTraceRefcnt::ResetLogFiles((*aArgv)[*aArgc - 1]); return false; } diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index aef1b2d2b11d..9db78b59af59 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -292,13 +292,15 @@ class BloatEntry { nsTraceRefcntStats mStats; }; -static void RecreateBloatView() { gBloatView = new BloatHash(256); } +static void CheckAndCreateBloatView() { + if (!gBloatView) { + gBloatView = new BloatHash(256); + } +} static BloatEntry* GetBloatEntry(const char* aTypeName, uint32_t aInstanceSize) { - if (!gBloatView) { - RecreateBloatView(); - } + CheckAndCreateBloatView(); BloatEntry* entry = gBloatView->Get(aTypeName); if (!entry && aInstanceSize > 0) { entry = new BloatEntry(aTypeName, aInstanceSize); @@ -474,7 +476,7 @@ static bool LogThisObj(intptr_t aSerialNumber) { using EnvCharType = mozilla::filesystem::Path::value_type; static bool InitLog(const EnvCharType* aEnvVar, const char* aMsg, - FILE** aResult) { + FILE** aResult, const char* aProcType) { #ifdef XP_WIN // This is gross, I know. const wchar_t* envvar = reinterpret_cast(aEnvVar); @@ -506,8 +508,7 @@ static bool InitLog(const EnvCharType* aEnvVar, const char* aMsg, fname.Cut(fname.Length() - 4, 4); } fname.Append('_'); - const char* processType = XRE_GetProcessTypeString(); - fname.AppendASCII(processType); + fname.AppendASCII(aProcType); fname.AppendLiteral("_pid"); fname.AppendInt((uint32_t)getpid()); if (hasLogExtension) { @@ -555,18 +556,13 @@ static void maybeUnregisterAndCloseFile(FILE*& aFile) { aFile = nullptr; } -static void InitTraceLog() { +static void DoInitTraceLog(const char* aProcType) { #ifdef XP_WIN # define ENVVAR(x) u"" x #else # define ENVVAR(x) x #endif - if (gInitialized) { - return; - } - gInitialized = true; - // Don't trace refcounts while recording or replaying, these are not // required to match up between the two executions. if (mozilla::recordreplay::IsRecordingOrReplaying()) { @@ -574,28 +570,33 @@ static void InitTraceLog() { } bool defined = - InitLog(ENVVAR("XPCOM_MEM_BLOAT_LOG"), "bloat/leaks", &gBloatLog); + InitLog(ENVVAR("XPCOM_MEM_BLOAT_LOG"), "bloat/leaks", &gBloatLog, aProcType); if (!defined) { - gLogLeaksOnly = InitLog(ENVVAR("XPCOM_MEM_LEAK_LOG"), "leaks", &gBloatLog); + gLogLeaksOnly = InitLog(ENVVAR("XPCOM_MEM_LEAK_LOG"), "leaks", &gBloatLog, aProcType); } if (defined || gLogLeaksOnly) { - RecreateBloatView(); + // Use the same bloat view, if there is, to keep it consistent + // through the fork server and content processes. + CheckAndCreateBloatView(); + if (!gBloatView) { NS_WARNING("out of memory"); maybeUnregisterAndCloseFile(gBloatLog); gLogLeaksOnly = false; } + } else if (gBloatView) { + nsTraceRefcnt::ResetStatistics(); } - InitLog(ENVVAR("XPCOM_MEM_REFCNT_LOG"), "refcounts", &gRefcntsLog); + InitLog(ENVVAR("XPCOM_MEM_REFCNT_LOG"), "refcounts", &gRefcntsLog, aProcType); - InitLog(ENVVAR("XPCOM_MEM_ALLOC_LOG"), "new/delete", &gAllocLog); + InitLog(ENVVAR("XPCOM_MEM_ALLOC_LOG"), "new/delete", &gAllocLog, aProcType); const char* classes = getenv("XPCOM_MEM_LOG_CLASSES"); #ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR if (classes) { - InitLog(ENVVAR("XPCOM_MEM_COMPTR_LOG"), "nsCOMPtr", &gCOMPtrLog); + InitLog(ENVVAR("XPCOM_MEM_COMPTR_LOG"), "nsCOMPtr", &gCOMPtrLog, aProcType); } else { if (getenv("XPCOM_MEM_COMPTR_LOG")) { fprintf(stdout, @@ -617,7 +618,13 @@ static void InitTraceLog() { if (classes) { // if XPCOM_MEM_LOG_CLASSES was set to some value, the value is interpreted // as a list of class names to track - gTypesToLog = new CharPtrSet(256); + // + // Use the same |gTypesToLog| and |gSerialNumbers| to keep them + // consistent through the fork server and content processes. + // Without this, counters will be incorrect. + if (!gTypesToLog) { + gTypesToLog = new CharPtrSet(256); + } fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- " @@ -628,7 +635,9 @@ static void InitTraceLog() { if (cm) { *cm = '\0'; } - gTypesToLog->PutEntry(cp); + if (!gTypesToLog->Contains(cp)) { + gTypesToLog->PutEntry(cp); + } fprintf(stdout, "%s ", cp); if (!cm) { break; @@ -638,7 +647,12 @@ static void InitTraceLog() { } fprintf(stdout, "\n"); - gSerialNumbers = new SerialHash(256); + if (!gSerialNumbers) { + gSerialNumbers = new SerialHash(256); + } + } else { + gTypesToLog = nullptr; + gSerialNumbers = nullptr; } const char* objects = getenv("XPCOM_MEM_LOG_OBJECTS"); @@ -702,6 +716,15 @@ static void InitTraceLog() { } } +static void InitTraceLog() { + if (gInitialized) { + return; + } + gInitialized = true; + + DoInitTraceLog(XRE_GetProcessTypeString()); +} + extern "C" { static void EnsureWrite(FILE* aStream, const char* aBuf, size_t aLen) { @@ -1141,18 +1164,28 @@ NS_LogCOMPtrRelease(void* aCOMPtr, nsISupports* aObject) { #endif // HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR } -void nsTraceRefcnt::Shutdown() { +static void ClearLogs(bool aKeepCounters) { gCodeAddressService = nullptr; - gBloatView = nullptr; - gTypesToLog = nullptr; + // These counters from the fork server process will be preserved + // for the content processes to keep them consistent. + if (!aKeepCounters) { + gBloatView = nullptr; + gTypesToLog = nullptr; + gSerialNumbers = nullptr; + } gObjectsToLog = nullptr; - gSerialNumbers = nullptr; + gLogJSStacks = false; + gLogLeaksOnly = false; maybeUnregisterAndCloseFile(gBloatLog); maybeUnregisterAndCloseFile(gRefcntsLog); maybeUnregisterAndCloseFile(gAllocLog); maybeUnregisterAndCloseFile(gCOMPtrLog); } +void nsTraceRefcnt::Shutdown() { + ClearLogs(false); +} + void nsTraceRefcnt::SetActivityIsLegal(bool aLegal) { if (gActivityTLS == BAD_TLS_INDEX) { PR_NewThreadPrivateIndex(&gActivityTLS, nullptr); @@ -1162,30 +1195,13 @@ void nsTraceRefcnt::SetActivityIsLegal(bool aLegal) { } #ifdef MOZ_ENABLE_FORKSERVER -void nsTraceRefcnt::ResetLogFiles() { -#ifdef XP_WIN -# define ENVVAR(x) u"" x -#else -# define ENVVAR(x) x -#endif - if (gBloatLog) { - maybeUnregisterAndCloseFile(gBloatLog); - bool defined = InitLog(ENVVAR("XPCOM_MEM_BLOAT_LOG"), "bloat/leaks", &gBloatLog); - if (!defined) { - InitLog(ENVVAR("XPCOM_MEM_LEAK_LOG"), "leaks", &gBloatLog); - } - } - if (gRefcntsLog) { - maybeUnregisterAndCloseFile(gRefcntsLog); - InitLog(ENVVAR("XPCOM_MEM_REFCNT_LOG"), "refcounts", &gRefcntsLog); - } - if (gAllocLog) { - maybeUnregisterAndCloseFile(gAllocLog); - InitLog(ENVVAR("XPCOM_MEM_ALLOC_LOG"), "new/delete", &gAllocLog); - } - if(gCOMPtrLog) { - maybeUnregisterAndCloseFile(gCOMPtrLog); - InitLog(ENVVAR("XPCOM_MEM_COMPTR_LOG"), "nsCOMPtr", &gCOMPtrLog); - } +void nsTraceRefcnt::ResetLogFiles(const char* aProcType) { + AutoRestore saveLogging(gLogging); + gLogging = NoLogging; + + ClearLogs(true); + + // Create log files with the correct process type in the name. + DoInitTraceLog(aProcType); } #endif diff --git a/xpcom/base/nsTraceRefcnt.h b/xpcom/base/nsTraceRefcnt.h index 35d142c4b643..acaa9cd2c368 100644 --- a/xpcom/base/nsTraceRefcnt.h +++ b/xpcom/base/nsTraceRefcnt.h @@ -30,7 +30,7 @@ class nsTraceRefcnt { static void SetActivityIsLegal(bool aLegal); #ifdef MOZ_ENABLE_FORKSERVER - static void ResetLogFiles(); + static void ResetLogFiles(const char* aProcType = nullptr); #endif };