bool TraceLoggerGraph::init(uint64_t startTimestamp) { auto fail = MakeScopeExit([&] { failed = true; }); if (!tree.init()) return false; if (!stack.init()) return false; if (!EnsureTraceLoggerGraphState()) return false; uint32_t loggerId = traceLoggerGraphState->nextLoggerId(); if (loggerId == uint32_t(-1)) return false; uint32_t pid = traceLoggerGraphState->pid(); js::UniqueChars dictFilename = AllocTraceLogFilename("tl-dict.%u.%d.json", pid, loggerId); dictFile = fopen(dictFilename.get(), "w"); if (!dictFile) return false; auto cleanupDict = MakeScopeExit([&] { fclose(dictFile); dictFile = nullptr; }); js::UniqueChars treeFilename = AllocTraceLogFilename("tl-tree.%u.%d.tl", pid, loggerId); treeFile = fopen(treeFilename.get(), "w+b"); if (!treeFile) return false; auto cleanupTree = MakeScopeExit([&] { fclose(treeFile); treeFile = nullptr; }); js::UniqueChars eventFilename = AllocTraceLogFilename("tl-event.%u.%d.tl", pid, loggerId); eventFile = fopen(eventFilename.get(), "wb"); if (!eventFile) return false; auto cleanupEvent = MakeScopeExit([&] { fclose(eventFile); eventFile = nullptr; }); // Create the top tree node and corresponding first stack item. TreeEntry& treeEntry = tree.pushUninitialized(); treeEntry.setStart(startTimestamp); treeEntry.setStop(0); treeEntry.setTextId(0); treeEntry.setHasChildren(false); treeEntry.setNextId(0); StackEntry& stackEntry = stack.pushUninitialized(); stackEntry.setTreeId(0); stackEntry.setLastChildId(0); stackEntry.setActive(true); if (fprintf(dictFile, "[") < 0) { fprintf(stderr, "TraceLogging: Error while writing.\n"); return false; } fail.release(); cleanupDict.release(); cleanupTree.release(); cleanupEvent.release(); return true; }