Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(774)

Unified Diff: base/trace_event/memory_dump_manager.cc

Issue 2836933002: memory-infra: Never kill memory-infra background thread (Closed)
Patch Set: sacrifice to the dark gods of TSAN Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/trace_event/memory_dump_manager.cc
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 02f2a6a8d45665abd5e89bd19d6736ab771bb999..5bd28dd65cd8d366250a270afa8d40c73dd1d108 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -182,7 +182,7 @@ void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
MemoryDumpManager::MemoryDumpManager()
: is_coordinator_(false),
- memory_tracing_enabled_(0),
+ is_enabled_(0),
tracing_process_id_(kInvalidTracingProcessId),
dumper_registrations_ignored_for_testing_(false),
heap_profiling_enabled_(false) {
@@ -197,6 +197,11 @@ MemoryDumpManager::MemoryDumpManager()
}
MemoryDumpManager::~MemoryDumpManager() {
+ AutoLock lock(lock_);
+ if (dump_thread_) {
+ dump_thread_->Stop();
+ dump_thread_.reset();
+ }
}
void MemoryDumpManager::EnableHeapProfilingIfNeeded() {
@@ -394,7 +399,7 @@ void MemoryDumpManager::UnregisterDumpProviderInternal(
DCHECK(!(*mdp_iter)->owned_dump_provider);
(*mdp_iter)->owned_dump_provider = std::move(owned_mdp);
} else if (strict_thread_check_blacklist_.count((*mdp_iter)->name) == 0 ||
- subtle::NoBarrier_Load(&memory_tracing_enabled_)) {
+ subtle::NoBarrier_Load(&is_enabled_)) {
// If dump provider's name is on |strict_thread_check_blacklist_|, then the
// DCHECK is fired only when tracing is enabled. Otherwise the DCHECK is
// fired even when tracing is not enabled (stricter).
@@ -437,7 +442,7 @@ void MemoryDumpManager::RequestGlobalDump(
const GlobalMemoryDumpCallback& callback) {
// Bail out immediately if tracing is not enabled at all or if the dump mode
// is not allowed.
- if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) ||
+ if (!UNLIKELY(subtle::NoBarrier_Load(&is_enabled_)) ||
!IsDumpModeAllowed(level_of_detail)) {
VLOG(1) << kLogPrefix << " failed because " << kTraceCategory
<< " tracing category is not enabled or the requested dump mode is "
@@ -492,6 +497,20 @@ bool MemoryDumpManager::IsDumpProviderRegisteredForTesting(
return false;
}
+scoped_refptr<base::SequencedTaskRunner>
+MemoryDumpManager::GetOrCreateBgTaskRunnerLocked() {
+ lock_.AssertAcquired();
+
+ if (dump_thread_)
+ return dump_thread_->task_runner();
+
+ dump_thread_ = MakeUnique<Thread>("MemoryInfra");
+ bool started = dump_thread_->Start();
+ CHECK(started);
+
+ return dump_thread_->task_runner();
+}
+
void MemoryDumpManager::CreateProcessDump(
const MemoryDumpRequestArgs& args,
const ProcessMemoryDumpCallback& callback) {
@@ -515,12 +534,9 @@ void MemoryDumpManager::CreateProcessDump(
{
AutoLock lock(lock_);
- // |dump_thread_| can be nullptr is tracing was disabled before reaching
- // here. SetupNextMemoryDump() is robust enough to tolerate it and will
- // NACK the dump.
pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
args, dump_providers_, session_state_, callback,
- dump_thread_ ? dump_thread_->task_runner() : nullptr));
+ GetOrCreateBgTaskRunnerLocked()));
// Safety check to prevent reaching here without calling RequestGlobalDump,
// with disallowed modes. If |session_state_| is null then tracing is
@@ -554,22 +570,22 @@ void MemoryDumpManager::SetupNextMemoryDump(
// (for discounting trace memory overhead) while holding the |lock_|.
TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();
- // |dump_thread_| might be destroyed before getting this point.
- // It means that tracing was disabled right before starting this dump.
- // Anyway either tracing is stopped or this was the last hop, create a trace
+ // MDM might have been disabled before getting to this point.
+ // Anyway either MDM is disabled or this was the last hop, create a trace
// event, add it to the trace and finalize process dump invoking the callback.
- if (!pmd_async_state->dump_thread_task_runner.get()) {
+ if (!subtle::NoBarrier_Load(&is_enabled_)) {
if (pmd_async_state->pending_dump_providers.empty()) {
- VLOG(1) << kLogPrefix << " failed because dump thread was destroyed"
+ VLOG(1) << kLogPrefix << " failed because MemoryDumpManager was disabled"
<< " before finalizing the dump";
} else {
- VLOG(1) << kLogPrefix << " failed because dump thread was destroyed"
+ VLOG(1) << kLogPrefix << " failed because MemoryDumpManager was disabled"
<< " before dumping "
<< pmd_async_state->pending_dump_providers.back().get()->name;
}
pmd_async_state->dump_successful = false;
pmd_async_state->pending_dump_providers.clear();
}
+
if (pmd_async_state->pending_dump_providers.empty())
return FinalizeDumpAndAddToTrace(std::move(pmd_async_state));
@@ -588,7 +604,7 @@ void MemoryDumpManager::SetupNextMemoryDump(
}
// If the dump provider did not specify a task runner affinity, dump on
- // |dump_thread_| which is already checked above for presence.
+ // |dump_thread_|.
SequencedTaskRunner* task_runner = mdpinfo->task_runner.get();
if (!task_runner) {
DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner);
@@ -789,12 +805,6 @@ void MemoryDumpManager::FinalizeDumpAndAddToTrace(
void MemoryDumpManager::Enable(
const TraceConfig::MemoryDumpConfig& memory_dump_config) {
- // Spin-up the thread used to invoke unbound dump providers.
- std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra"));
- if (!dump_thread->Start()) {
- LOG(ERROR) << "Failed to start the memory-infra thread for tracing";
- return;
- }
scoped_refptr<MemoryDumpSessionState> session_state =
new MemoryDumpSessionState;
@@ -830,10 +840,7 @@ void MemoryDumpManager::Enable(
DCHECK(!request_dump_function_.is_null());
session_state_ = session_state;
- DCHECK(!dump_thread_);
- dump_thread_ = std::move(dump_thread);
-
- subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
+ subtle::NoBarrier_Store(&is_enabled_, 1);
MemoryDumpScheduler::Config periodic_config;
bool peak_detector_configured = false;
@@ -855,7 +862,7 @@ void MemoryDumpManager::Enable(
MemoryPeakDetector::GetInstance()->Setup(
BindRepeating(&MemoryDumpManager::GetDumpProvidersForPolling,
Unretained(this)),
- dump_thread_->task_runner(),
+ GetOrCreateBgTaskRunnerLocked(),
BindRepeating(&OnPeakDetected, trigger.level_of_detail));
MemoryPeakDetector::Config peak_config;
@@ -868,7 +875,7 @@ void MemoryDumpManager::Enable(
// When peak detection is enabled, trigger a dump straight away as it
// gives a good reference point for analyzing the trace.
if (is_coordinator_) {
- dump_thread_->task_runner()->PostTask(
+ GetOrCreateBgTaskRunnerLocked()->PostTask(
FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail));
}
}
@@ -877,7 +884,7 @@ void MemoryDumpManager::Enable(
// Only coordinator process triggers periodic global memory dumps.
if (is_coordinator_ && !periodic_config.triggers.empty()) {
MemoryDumpScheduler::GetInstance()->Start(periodic_config,
- dump_thread_->task_runner());
+ GetOrCreateBgTaskRunnerLocked());
}
}
@@ -885,22 +892,15 @@ void MemoryDumpManager::Disable() {
// There might be a memory dump in progress while this happens. Therefore,
// ensure that the MDM state which depends on the tracing enabled / disabled
// state is always accessed by the dumping methods holding the |lock_|.
- if (!subtle::NoBarrier_Load(&memory_tracing_enabled_))
+ if (!subtle::NoBarrier_Load(&is_enabled_))
return;
- subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
- std::unique_ptr<Thread> dump_thread;
+ subtle::NoBarrier_Store(&is_enabled_, 0);
{
AutoLock lock(lock_);
MemoryDumpScheduler::GetInstance()->Stop();
MemoryPeakDetector::GetInstance()->TearDown();
- dump_thread = std::move(dump_thread_);
session_state_ = nullptr;
}
-
- // Thread stops are blocking and must be performed outside of the |lock_|
- // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it).
- if (dump_thread)
- dump_thread->Stop();
}
bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) {
@@ -915,7 +915,7 @@ MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
const MemoryDumpProviderInfo::OrderedSet& dump_providers,
scoped_refptr<MemoryDumpSessionState> session_state,
ProcessMemoryDumpCallback callback,
- scoped_refptr<SingleThreadTaskRunner> dump_thread_task_runner)
+ scoped_refptr<SequencedTaskRunner> dump_thread_task_runner)
: req_args(req_args),
session_state(std::move(session_state)),
callback(callback),
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698