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

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

Issue 1884573002: Fix race condition when dump providers invoked within destroyed state (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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 #include <utility> 8 #include <utility>
9 9
10 #include "base/atomic_sequence_num.h" 10 #include "base/atomic_sequence_num.h"
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs 405 // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs
406 // in the PostTask below don't end up registering their own dump providers 406 // in the PostTask below don't end up registering their own dump providers
407 // (for discounting trace memory overhead) while holding the |lock_|. 407 // (for discounting trace memory overhead) while holding the |lock_|.
408 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); 408 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();
409 409
410 // If this was the last hop, create a trace event, add it to the trace and 410 // If this was the last hop, create a trace event, add it to the trace and
411 // finalize process dump (invoke callback). 411 // finalize process dump (invoke callback).
412 if (pmd_async_state->pending_dump_providers.empty()) 412 if (pmd_async_state->pending_dump_providers.empty())
413 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); 413 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state));
414 414
415 // |dump_thread_| might be destroyed before getting this point.
416 // It means that tracing was disabled a moment ago.
417 if (!pmd_async_state->dump_thread_task_runner.get()) {
Primiano Tucci (use gerrit) 2016/04/13 17:08:41 Ok looking a bit more to this CL it seems that the
kraynov 2016/04/13 17:17:41 Don't know the reason but it seems to be intention
418 pmd_async_state->dump_successful = false;
419 while (!pmd_async_state->pending_dump_providers.empty()) {
420 pmd_async_state->pending_dump_providers.pop_back();
421 }
422 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state));
423 }
424
415 // Read MemoryDumpProviderInfo thread safety considerations in 425 // Read MemoryDumpProviderInfo thread safety considerations in
416 // memory_dump_manager.h when accessing |mdpinfo| fields. 426 // memory_dump_manager.h when accessing |mdpinfo| fields.
417 MemoryDumpProviderInfo* mdpinfo = 427 MemoryDumpProviderInfo* mdpinfo =
418 pmd_async_state->pending_dump_providers.back().get(); 428 pmd_async_state->pending_dump_providers.back().get();
419 429
420 // If the dump provider did not specify a task runner affinity, dump on 430 // If the dump provider did not specify a task runner affinity, dump on
421 // |dump_thread_|. Note that |dump_thread_| might have been destroyed 431 // |dump_thread_| which is already checked above for presence.
422 // meanwhile.
423 SequencedTaskRunner* task_runner = mdpinfo->task_runner.get(); 432 SequencedTaskRunner* task_runner = mdpinfo->task_runner.get();
424 if (!task_runner) { 433 if (!task_runner) {
425 DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner); 434 DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner);
426 task_runner = pmd_async_state->dump_thread_task_runner.get(); 435 task_runner = pmd_async_state->dump_thread_task_runner.get();
427 if (!task_runner) {
428 // If tracing was disabled before reaching CreateProcessDump() the
429 // dump_thread_ would have been already torn down. Nack current dump and
430 // continue.
431 pmd_async_state->dump_successful = false;
432 pmd_async_state->pending_dump_providers.pop_back();
433 return SetupNextMemoryDump(std::move(pmd_async_state));
434 }
435 } 436 }
436 437
437 if (mdpinfo->options.dumps_on_single_thread_task_runner && 438 if (mdpinfo->options.dumps_on_single_thread_task_runner &&
438 task_runner->RunsTasksOnCurrentThread()) { 439 task_runner->RunsTasksOnCurrentThread()) {
439 // If |dumps_on_single_thread_task_runner| is true then no PostTask is 440 // If |dumps_on_single_thread_task_runner| is true then no PostTask is
440 // required if we are on the right thread. 441 // required if we are on the right thread.
441 return InvokeOnMemoryDump(pmd_async_state.release()); 442 return InvokeOnMemoryDump(pmd_async_state.release());
442 } 443 }
443 444
444 bool did_post_task = task_runner->PostTask( 445 bool did_post_task = task_runner->PostTask(
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 682
682 void MemoryDumpManager::OnTraceLogDisabled() { 683 void MemoryDumpManager::OnTraceLogDisabled() {
683 // There might be a memory dump in progress while this happens. Therefore, 684 // There might be a memory dump in progress while this happens. Therefore,
684 // ensure that the MDM state which depends on the tracing enabled / disabled 685 // ensure that the MDM state which depends on the tracing enabled / disabled
685 // state is always accessed by the dumping methods holding the |lock_|. 686 // state is always accessed by the dumping methods holding the |lock_|.
686 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); 687 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
687 std::unique_ptr<Thread> dump_thread; 688 std::unique_ptr<Thread> dump_thread;
688 { 689 {
689 AutoLock lock(lock_); 690 AutoLock lock(lock_);
690 dump_thread = std::move(dump_thread_); 691 dump_thread = std::move(dump_thread_);
691 session_state_ = nullptr;
692 } 692 }
693 693
694 // Thread stops are blocking and must be performed outside of the |lock_| 694 // Thread stops are blocking and must be performed outside of the |lock_|
695 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). 695 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it).
696 periodic_dump_timer_.Stop(); 696 periodic_dump_timer_.Stop();
697 if (dump_thread) 697 if (dump_thread) {
698 dump_thread->Stop(); 698 dump_thread->Stop();
699 session_state_ = nullptr;
Primiano Tucci (use gerrit) 2016/04/13 17:08:41 why are you moving this outside of the lock? we sh
kraynov 2016/04/13 17:17:41 Acknowledged.
700 }
699 } 701 }
700 702
701 uint64_t MemoryDumpManager::GetTracingProcessId() const { 703 uint64_t MemoryDumpManager::GetTracingProcessId() const {
702 return delegate_->GetTracingProcessId(); 704 return delegate_->GetTracingProcessId();
703 } 705 }
704 706
705 MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo( 707 MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
706 MemoryDumpProvider* dump_provider, 708 MemoryDumpProvider* dump_provider,
707 const char* name, 709 const char* name,
708 scoped_refptr<SequencedTaskRunner> task_runner, 710 scoped_refptr<SequencedTaskRunner> task_runner,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 if (iter == process_dumps.end()) { 755 if (iter == process_dumps.end()) {
754 std::unique_ptr<ProcessMemoryDump> new_pmd( 756 std::unique_ptr<ProcessMemoryDump> new_pmd(
755 new ProcessMemoryDump(session_state)); 757 new ProcessMemoryDump(session_state));
756 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; 758 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first;
757 } 759 }
758 return iter->second.get(); 760 return iter->second.get();
759 } 761 }
760 762
761 } // namespace trace_event 763 } // namespace trace_event
762 } // namespace base 764 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | base/trace_event/memory_dump_manager_unittest.cc » ('j') | base/trace_event/memory_dump_manager_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698