Bug 1604084 - Fix log names of leak checking and refactor it. r=gsvelto

Differential Revision: https://phabricator.services.mozilla.com/D57222

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Thinker Li 2019-12-18 17:02:10 +00:00
parent 33fd265be2
commit dae3528029
3 changed files with 72 additions and 54 deletions

View File

@ -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;
}

View File

@ -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<const wchar_t*>(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<LoggingType> saveLogging(gLogging);
gLogging = NoLogging;
ClearLogs(true);
// Create log files with the correct process type in the name.
DoInitTraceLog(aProcType);
}
#endif

View File

@ -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
};