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

Side by Side Diff: base/trace_event/memory_dump_manager.cc

Issue 1107093004: [tracing] Simplify MemoryDumpProvider interface (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Keep protected dtor Created 5 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/trace_event/memory_dump_manager.h" 5 #include "base/trace_event/memory_dump_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 137 }
138 138
139 // static 139 // static
140 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { 140 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
141 if (instance) 141 if (instance)
142 instance->skip_core_dumpers_auto_registration_for_testing_ = true; 142 instance->skip_core_dumpers_auto_registration_for_testing_ = true;
143 g_instance_for_testing = instance; 143 g_instance_for_testing = instance;
144 } 144 }
145 145
146 MemoryDumpManager::MemoryDumpManager() 146 MemoryDumpManager::MemoryDumpManager()
147 : dump_provider_currently_active_(nullptr), 147 : delegate_(nullptr),
148 delegate_(nullptr),
149 memory_tracing_enabled_(0), 148 memory_tracing_enabled_(0),
150 skip_core_dumpers_auto_registration_for_testing_(false) { 149 skip_core_dumpers_auto_registration_for_testing_(false) {
151 g_next_guid.GetNext(); // Make sure that first guid is not zero. 150 g_next_guid.GetNext(); // Make sure that first guid is not zero.
152 } 151 }
153 152
154 MemoryDumpManager::~MemoryDumpManager() { 153 MemoryDumpManager::~MemoryDumpManager() {
155 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this); 154 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
156 } 155 }
157 156
158 void MemoryDumpManager::Initialize() { 157 void MemoryDumpManager::Initialize() {
(...skipping 12 matching lines...) Expand all
171 RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); 170 RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
172 #endif 171 #endif
173 } 172 }
174 173
175 void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) { 174 void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
176 AutoLock lock(lock_); 175 AutoLock lock(lock_);
177 DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_); 176 DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
178 delegate_ = delegate; 177 delegate_ = delegate;
179 } 178 }
180 179
180 void MemoryDumpManager::RegisterDumpProvider(
181 MemoryDumpProvider* mdp,
182 const scoped_refptr<SingleThreadTaskRunner>& task_runner) {
183 MemoryDumpProviderInfo mdp_info(task_runner);
184 AutoLock lock(lock_);
185 dump_providers_.insert(std::make_pair(mdp, mdp_info));
186 }
187
181 void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) { 188 void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
182 AutoLock lock(lock_); 189 RegisterDumpProvider(mdp, nullptr);
183 dump_providers_registered_.insert(mdp);
184 } 190 }
185 191
186 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { 192 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
187 AutoLock lock(lock_); 193 AutoLock lock(lock_);
188 194
195 auto it = dump_providers_.find(mdp);
196 if (it == dump_providers_.end())
197 return;
198
199 const MemoryDumpProviderInfo& mdp_info = it->second;
189 // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe 200 // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
190 // only if the MDP has specified a thread affinity (via task_runner()) AND 201 // only if the MDP has specified a thread affinity (via task_runner()) AND
191 // the unregistration happens on the same thread (so the MDP cannot unregister 202 // the unregistration happens on the same thread (so the MDP cannot unregister
192 // and DumpInto() at the same time). 203 // and OnMemoryDump() at the same time).
193 // Otherwise, it is not possible to guarantee that its unregistration is 204 // Otherwise, it is not possible to guarantee that its unregistration is
194 // race-free. If you hit this DCHECK, your MDP has a bug. 205 // race-free. If you hit this DCHECK, your MDP has a bug.
195 DCHECK_IMPLIES( 206 DCHECK_IMPLIES(
196 subtle::NoBarrier_Load(&memory_tracing_enabled_), 207 subtle::NoBarrier_Load(&memory_tracing_enabled_),
197 mdp->task_runner() && mdp->task_runner()->BelongsToCurrentThread()) 208 mdp_info.task_runner && mdp_info.task_runner->BelongsToCurrentThread())
198 << "The MemoryDumpProvider " << mdp->GetFriendlyName() << " attempted to " 209 << "The MemoryDumpProvider attempted to unregister itself in a racy way. "
199 << "unregister itself in a racy way. Please file a crbug."; 210 << " Please file a crbug.";
200 211
201 // Remove from the enabled providers list. This is to deal with the case that 212 // Remove from the enabled providers list. This is to deal with the case that
202 // UnregisterDumpProvider is called while the trace is enabled. 213 // UnregisterDumpProvider is called while the trace is enabled.
203 dump_providers_enabled_.erase(mdp); 214 dump_providers_.erase(it);
204 dump_providers_registered_.erase(mdp);
205 } 215 }
206 216
207 void MemoryDumpManager::RequestGlobalDump( 217 void MemoryDumpManager::RequestGlobalDump(
208 MemoryDumpType dump_type, 218 MemoryDumpType dump_type,
209 const MemoryDumpCallback& callback) { 219 const MemoryDumpCallback& callback) {
210 // Bail out immediately if tracing is not enabled at all. 220 // Bail out immediately if tracing is not enabled at all.
211 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) 221 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
212 return; 222 return;
213 223
214 const uint64 guid = 224 const uint64 guid =
(...skipping 22 matching lines...) Expand all
237 } 247 }
238 248
239 // Creates a memory dump for the current process and appends it to the trace. 249 // Creates a memory dump for the current process and appends it to the trace.
240 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, 250 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
241 const MemoryDumpCallback& callback) { 251 const MemoryDumpCallback& callback) {
242 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder( 252 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder(
243 new ProcessMemoryDumpHolder(args, session_state_, callback)); 253 new ProcessMemoryDumpHolder(args, session_state_, callback));
244 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump; 254 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
245 bool did_any_provider_dump = false; 255 bool did_any_provider_dump = false;
246 256
247 // Iterate over the active dump providers and invoke DumpInto(pmd). 257 // Iterate over the active dump providers and invoke OnMemoryDump(pmd).
248 // The MDM guarantees linearity (at most one MDP is active within one 258 // The MDM guarantees linearity (at most one MDP is active within one
249 // process) and thread-safety (MDM enforces the right locking when entering / 259 // process) and thread-safety (MDM enforces the right locking when entering /
250 // leaving the MDP.DumpInto() call). This is to simplify the clients' design 260 // leaving the MDP.OnMemoryDump() call). This is to simplify the clients'
261 // design
251 // and not let the MDPs worry about locking. 262 // and not let the MDPs worry about locking.
252 // As regards thread affinity, depending on the MDP configuration (see 263 // As regards thread affinity, depending on the MDP configuration (see
253 // memory_dump_provider.h), the DumpInto() invocation can happen: 264 // memory_dump_provider.h), the OnMemoryDump() invocation can happen:
254 // - Synchronousy on the MDM thread, when MDP.task_runner() is not set. 265 // - Synchronousy on the MDM thread, when MDP.task_runner() is not set.
255 // - Posted on MDP.task_runner(), when MDP.task_runner() is set. 266 // - Posted on MDP.task_runner(), when MDP.task_runner() is set.
256 { 267 {
257 AutoLock lock(lock_); 268 AutoLock lock(lock_);
258 for (auto dump_provider_iter = dump_providers_enabled_.begin(); 269 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) {
259 dump_provider_iter != dump_providers_enabled_.end();) { 270 MemoryDumpProvider* mdp = it->first;
260 // InvokeDumpProviderLocked will remove the MDP from the set if it fails. 271 MemoryDumpProviderInfo* mdp_info = &it->second;
261 MemoryDumpProvider* mdp = *dump_provider_iter; 272 if (mdp_info->disabled)
262 ++dump_provider_iter; 273 continue;
263 if (mdp->task_runner()) { 274 if (mdp_info->task_runner) {
264 // The DumpInto() call must be posted. 275 // The OnMemoryDump() call must be posted.
265 bool did_post_async_task = mdp->task_runner()->PostTask( 276 bool did_post_async_task = mdp_info->task_runner->PostTask(
266 FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump, 277 FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
267 Unretained(this), Unretained(mdp), pmd_holder)); 278 Unretained(this), Unretained(mdp), pmd_holder));
268 // The thread underlying the TaskRunner might have gone away. 279 // The thread underlying the TaskRunner might have gone away.
269 if (did_post_async_task) 280 if (did_post_async_task)
270 ++pmd_holder->num_pending_async_requests; 281 ++pmd_holder->num_pending_async_requests;
271 } else { 282 } else {
272 // Invoke the dump provider synchronously. 283 // Invoke the dump provider synchronously.
273 did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd); 284 did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd);
274 } 285 }
275 } 286 }
276 } // AutoLock 287 } // AutoLock
277 288
278 // If at least one synchronous provider did dump and there are no pending 289 // If at least one synchronous provider did dump and there are no pending
279 // asynchronous requests, add the dump to the trace and invoke the callback 290 // asynchronous requests, add the dump to the trace and invoke the callback
280 // straight away (FinalizeDumpAndAddToTrace() takes care of the callback). 291 // straight away (FinalizeDumpAndAddToTrace() takes care of the callback).
281 if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0) 292 if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0)
282 FinalizeDumpAndAddToTrace(pmd_holder); 293 FinalizeDumpAndAddToTrace(pmd_holder);
283 } 294 }
284 295
285 // Invokes the MemoryDumpProvider.DumpInto(), taking care of the failsafe logic 296 // Invokes the MemoryDumpProvider.OnMemoryDump(), taking care of the fail-safe
286 // which disables the dumper when failing (crbug.com/461788). 297 // logic which disables the dumper when failing (crbug.com/461788).
287 bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp, 298 bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
288 ProcessMemoryDump* pmd) { 299 ProcessMemoryDump* pmd) {
289 lock_.AssertAcquired(); 300 lock_.AssertAcquired();
290 dump_provider_currently_active_ = mdp; 301 bool dump_successful = mdp->OnMemoryDump(pmd);
291 bool dump_successful = mdp->DumpInto(pmd);
292 dump_provider_currently_active_ = nullptr;
293 if (!dump_successful) { 302 if (!dump_successful) {
294 LOG(ERROR) << "The memory dumper " << mdp->GetFriendlyName() 303 LOG(ERROR) << "The memory dumper failed, possibly due to sandboxing "
295 << " failed, possibly due to sandboxing (crbug.com/461788), " 304 "(crbug.com/461788), disabling it for current process. Try "
296 "disabling it for current process. Try restarting chrome " 305 "restarting chrome with the --no-sandbox switch.";
297 "with the --no-sandbox switch."; 306 dump_providers_.find(mdp)->second.disabled = true;
298 dump_providers_enabled_.erase(mdp);
299 } 307 }
300 return dump_successful; 308 return dump_successful;
301 } 309 }
302 310
303 // This is posted to arbitrary threads as a continuation of CreateProcessDump(), 311 // This is posted to arbitrary threads as a continuation of CreateProcessDump(),
304 // when one or more MemoryDumpProvider(s) require the DumpInto() call to happen 312 // when one or more MemoryDumpProvider(s) require the OnMemoryDump() call to
305 // on a different thread. 313 // happen on a different thread.
306 void MemoryDumpManager::ContinueAsyncProcessDump( 314 void MemoryDumpManager::ContinueAsyncProcessDump(
307 MemoryDumpProvider* mdp, 315 MemoryDumpProvider* mdp,
308 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) { 316 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) {
309 bool should_finalize_dump = false; 317 bool should_finalize_dump = false;
310 { 318 {
311 // The lock here is to guarantee that different asynchronous dumps on 319 // The lock here is to guarantee that different asynchronous dumps on
312 // different threads are still serialized, so that the MemoryDumpProvider 320 // different threads are still serialized, so that the MemoryDumpProvider
313 // has a consistent view of the |pmd| argument passed. 321 // has a consistent view of the |pmd| argument passed.
314 AutoLock lock(lock_); 322 AutoLock lock(lock_);
315 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump; 323 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
316 324
317 // Check if the MemoryDumpProvider is still there. It might have been 325 // Check if the MemoryDumpProvider is still there. It might have been
318 // destroyed and unregistered while hopping threads. 326 // destroyed and unregistered while hopping threads.
319 if (dump_providers_enabled_.count(mdp)) 327 if (dump_providers_.count(mdp))
320 InvokeDumpProviderLocked(mdp, pmd); 328 InvokeDumpProviderLocked(mdp, pmd);
321 329
322 // Finalize the dump appending it to the trace if this was the last 330 // Finalize the dump appending it to the trace if this was the last
323 // asynchronous request pending. 331 // asynchronous request pending.
324 --pmd_holder->num_pending_async_requests; 332 --pmd_holder->num_pending_async_requests;
325 if (pmd_holder->num_pending_async_requests == 0) 333 if (pmd_holder->num_pending_async_requests == 0)
326 should_finalize_dump = true; 334 should_finalize_dump = true;
327 } // AutoLock(lock_) 335 } // AutoLock(lock_)
328 336
329 if (should_finalize_dump) 337 if (should_finalize_dump)
330 FinalizeDumpAndAddToTrace(pmd_holder); 338 FinalizeDumpAndAddToTrace(pmd_holder);
331 } 339 }
332 340
333 void MemoryDumpManager::OnTraceLogEnabled() { 341 void MemoryDumpManager::OnTraceLogEnabled() {
334 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter 342 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter
335 // to figure out (and cache) which dumpers should be enabled or not. 343 // to figure out (and cache) which dumpers should be enabled or not.
336 // For the moment piggy back everything on the generic "memory" category. 344 // For the moment piggy back everything on the generic "memory" category.
337 bool enabled; 345 bool enabled;
338 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); 346 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
339 347
340 AutoLock lock(lock_); 348 AutoLock lock(lock_);
341 349
342 // There is no point starting the tracing without a delegate. 350 // There is no point starting the tracing without a delegate.
343 if (!enabled || !delegate_) { 351 if (!enabled || !delegate_) {
344 dump_providers_enabled_.clear(); 352 // Disable all the providers.
353 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
354 it->second.disabled = true;
345 return; 355 return;
346 } 356 }
347 357
348 // Merge the dictionary of allocator attributes from all dump providers
349 // into the session state.
350 session_state_ = new MemoryDumpSessionState(); 358 session_state_ = new MemoryDumpSessionState();
351 for (const MemoryDumpProvider* mdp : dump_providers_registered_) { 359 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
352 session_state_->allocators_attributes_type_info.Update( 360 it->second.disabled = false;
353 mdp->allocator_attributes_type_info()); 361
354 }
355 dump_providers_enabled_ = dump_providers_registered_;
356 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); 362 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
357 363
358 if (delegate_->IsCoordinatorProcess()) { 364 if (delegate_->IsCoordinatorProcess()) {
359 periodic_dump_timer_.Start(FROM_HERE, 365 periodic_dump_timer_.Start(FROM_HERE,
360 TimeDelta::FromSeconds(kDumpIntervalSeconds), 366 TimeDelta::FromSeconds(kDumpIntervalSeconds),
361 base::Bind(&RequestPeriodicGlobalDump)); 367 base::Bind(&RequestPeriodicGlobalDump));
362 } 368 }
363 } 369 }
364 370
365 void MemoryDumpManager::OnTraceLogDisabled() { 371 void MemoryDumpManager::OnTraceLogDisabled() {
366 AutoLock lock(lock_); 372 AutoLock lock(lock_);
367 periodic_dump_timer_.Stop(); 373 periodic_dump_timer_.Stop();
368 dump_providers_enabled_.clear();
369 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); 374 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
370 session_state_ = nullptr; 375 session_state_ = nullptr;
371 } 376 }
372 377
378 MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
379 const scoped_refptr<SingleThreadTaskRunner>& task_runner)
380 : task_runner(task_runner), disabled(false) {
381 }
382 MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {
383 }
384
373 } // namespace trace_event 385 } // namespace trace_event
374 } // namespace base 386 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | base/trace_event/memory_dump_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698