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

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

Powered by Google App Engine
This is Rietveld 408576698