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

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

Issue 1923193002: Protect TraceLog::enabled_state_observer_list_ with a dedicated lock (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: New policy on EnabledStateObserver's callbacks, and remove TraceEventTestFixture.SelfRemovingObserv… Created 4 years, 7 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/trace_log.h" 5 #include "base/trace_event/trace_log.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 562
563 void TraceLog::GetKnownCategoryGroups( 563 void TraceLog::GetKnownCategoryGroups(
564 std::vector<std::string>* category_groups) { 564 std::vector<std::string>* category_groups) {
565 AutoLock lock(lock_); 565 AutoLock lock(lock_);
566 size_t category_index = base::subtle::NoBarrier_Load(&g_category_index); 566 size_t category_index = base::subtle::NoBarrier_Load(&g_category_index);
567 for (size_t i = g_num_builtin_categories; i < category_index; i++) 567 for (size_t i = g_num_builtin_categories; i < category_index; i++)
568 category_groups->push_back(g_category_groups[i]); 568 category_groups->push_back(g_category_groups[i]);
569 } 569 }
570 570
571 void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) { 571 void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) {
572 std::vector<EnabledStateObserver*> observer_list; 572 AutoLock lock(lock_);
573 {
574 AutoLock lock(lock_);
575 573
576 // Can't enable tracing when Flush() is in progress. 574 // Can't enable tracing when Flush() is in progress.
577 DCHECK(!flush_task_runner_); 575 DCHECK(!flush_task_runner_);
578 576
579 InternalTraceOptions new_options = 577 InternalTraceOptions new_options =
580 GetInternalOptionsFromTraceConfig(trace_config); 578 GetInternalOptionsFromTraceConfig(trace_config);
581 579
582 InternalTraceOptions old_options = trace_options(); 580 InternalTraceOptions old_options = trace_options();
583 581
584 if (IsEnabled()) { 582 if (IsEnabled()) {
585 if (new_options != old_options) { 583 if (new_options != old_options) {
586 DLOG(ERROR) << "Attempting to re-enable tracing with a different " 584 DLOG(ERROR) << "Attempting to re-enable tracing with a different "
587 << "set of options."; 585 << "set of options.";
588 }
589
590 if (mode != mode_) {
591 DLOG(ERROR) << "Attempting to re-enable tracing with a different mode.";
592 }
593
594 trace_config_.Merge(trace_config);
595 UpdateCategoryGroupEnabledFlags();
596 return;
597 } 586 }
598 587
599 if (dispatching_to_observer_list_) { 588 if (mode != mode_) {
600 DLOG(ERROR) 589 DLOG(ERROR) << "Attempting to re-enable tracing with a different mode.";
601 << "Cannot manipulate TraceLog::Enabled state from an observer.";
602 return;
603 } 590 }
604 591
605 mode_ = mode; 592 trace_config_.Merge(trace_config);
593 UpdateCategoryGroupEnabledFlags();
594 return;
595 }
606 596
607 if (new_options != old_options) { 597 if (dispatching_to_observer_list_) {
608 subtle::NoBarrier_Store(&trace_options_, new_options); 598 DLOG(ERROR)
609 UseNextTraceBuffer(); 599 << "Cannot manipulate TraceLog::Enabled state from an observer.";
600 return;
601 }
602
603 mode_ = mode;
604
605 if (new_options != old_options) {
606 subtle::NoBarrier_Store(&trace_options_, new_options);
607 UseNextTraceBuffer();
608 }
609
610 num_traces_recorded_++;
611
612 trace_config_ = TraceConfig(trace_config);
613 UpdateCategoryGroupEnabledFlags();
614 UpdateSyntheticDelaysFromTraceConfig();
615
616 if (new_options & kInternalEnableSampling) {
617 sampling_thread_.reset(new TraceSamplingThread);
618 sampling_thread_->RegisterSampleBucket(
619 &g_trace_state[0], "bucket0",
620 Bind(&TraceSamplingThread::DefaultSamplingCallback));
621 sampling_thread_->RegisterSampleBucket(
622 &g_trace_state[1], "bucket1",
623 Bind(&TraceSamplingThread::DefaultSamplingCallback));
624 sampling_thread_->RegisterSampleBucket(
625 &g_trace_state[2], "bucket2",
626 Bind(&TraceSamplingThread::DefaultSamplingCallback));
627 if (!PlatformThread::Create(0, sampling_thread_.get(),
628 &sampling_thread_handle_)) {
629 DCHECK(false) << "failed to create thread";
610 } 630 }
611
612 num_traces_recorded_++;
613
614 trace_config_ = TraceConfig(trace_config);
615 UpdateCategoryGroupEnabledFlags();
616 UpdateSyntheticDelaysFromTraceConfig();
617
618 if (new_options & kInternalEnableSampling) {
619 sampling_thread_.reset(new TraceSamplingThread);
620 sampling_thread_->RegisterSampleBucket(
621 &g_trace_state[0], "bucket0",
622 Bind(&TraceSamplingThread::DefaultSamplingCallback));
623 sampling_thread_->RegisterSampleBucket(
624 &g_trace_state[1], "bucket1",
625 Bind(&TraceSamplingThread::DefaultSamplingCallback));
626 sampling_thread_->RegisterSampleBucket(
627 &g_trace_state[2], "bucket2",
628 Bind(&TraceSamplingThread::DefaultSamplingCallback));
629 if (!PlatformThread::Create(0, sampling_thread_.get(),
630 &sampling_thread_handle_)) {
631 DCHECK(false) << "failed to create thread";
632 }
633 }
634
635 dispatching_to_observer_list_ = true;
636 observer_list = enabled_state_observer_list_;
637 } 631 }
638 // Notify observers outside the lock in case they trigger trace events.
639 for (size_t i = 0; i < observer_list.size(); ++i)
640 observer_list[i]->OnTraceLogEnabled();
641 632
642 { 633 {
643 AutoLock lock(lock_); 634 AutoLock observer_list_lock(observer_list_lock_);
635 dispatching_to_observer_list_ = true;
636 {
637 // Notify observers outside the lock in case they trigger trace events.
638 AutoUnlock unlock(lock_);
639 for (size_t i = 0; i < enabled_state_observer_list_.size(); ++i)
640 enabled_state_observer_list_[i]->OnTraceLogEnabled();
641 }
644 dispatching_to_observer_list_ = false; 642 dispatching_to_observer_list_ = false;
645 } 643 }
646 } 644 }
647 645
648 void TraceLog::SetArgumentFilterPredicate( 646 void TraceLog::SetArgumentFilterPredicate(
649 const ArgumentFilterPredicate& argument_filter_predicate) { 647 const ArgumentFilterPredicate& argument_filter_predicate) {
650 AutoLock lock(lock_); 648 AutoLock lock(lock_);
651 DCHECK(!argument_filter_predicate.is_null()); 649 DCHECK(!argument_filter_predicate.is_null());
652 DCHECK(argument_filter_predicate_.is_null()); 650 DCHECK(argument_filter_predicate_.is_null());
653 argument_filter_predicate_ = argument_filter_predicate; 651 argument_filter_predicate_ = argument_filter_predicate;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 707
710 trace_config_.Clear(); 708 trace_config_.Clear();
711 subtle::NoBarrier_Store(&watch_category_, 0); 709 subtle::NoBarrier_Store(&watch_category_, 0);
712 watch_event_name_ = ""; 710 watch_event_name_ = "";
713 UpdateCategoryGroupEnabledFlags(); 711 UpdateCategoryGroupEnabledFlags();
714 AddMetadataEventsWhileLocked(); 712 AddMetadataEventsWhileLocked();
715 713
716 // Remove metadata events so they will not get added to a subsequent trace. 714 // Remove metadata events so they will not get added to a subsequent trace.
717 metadata_events_.clear(); 715 metadata_events_.clear();
718 716
719 dispatching_to_observer_list_ = true;
720 std::vector<EnabledStateObserver*> observer_list =
721 enabled_state_observer_list_;
722
723 { 717 {
724 // Dispatch to observers outside the lock in case the observer triggers a 718 AutoLock observer_list_lock(observer_list_lock_);
725 // trace event. 719 dispatching_to_observer_list_ = true;
726 AutoUnlock unlock(lock_); 720 {
727 for (size_t i = 0; i < observer_list.size(); ++i) 721 // Dispatch to observers outside the lock in case the observer triggers a
728 observer_list[i]->OnTraceLogDisabled(); 722 // trace event.
723 AutoUnlock unlock(lock_);
724 for (size_t i = 0; i < enabled_state_observer_list_.size(); ++i)
725 enabled_state_observer_list_[i]->OnTraceLogDisabled();
726 }
727 dispatching_to_observer_list_ = false;
729 } 728 }
730 dispatching_to_observer_list_ = false;
731 } 729 }
732 730
733 int TraceLog::GetNumTracesRecorded() { 731 int TraceLog::GetNumTracesRecorded() {
734 AutoLock lock(lock_); 732 AutoLock lock(lock_);
735 if (!IsEnabled()) 733 if (!IsEnabled())
736 return -1; 734 return -1;
737 return num_traces_recorded_; 735 return num_traces_recorded_;
738 } 736 }
739 737
740 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) { 738 void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) {
741 AutoLock lock(lock_); 739 AutoLock observer_list_lock(observer_list_lock_);
742 enabled_state_observer_list_.push_back(listener); 740 enabled_state_observer_list_.push_back(listener);
743 } 741 }
744 742
745 void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) { 743 void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {
746 AutoLock lock(lock_); 744 AutoLock observer_list_lock(observer_list_lock_);
747 std::vector<EnabledStateObserver*>::iterator it = 745 std::vector<EnabledStateObserver*>::iterator it =
748 std::find(enabled_state_observer_list_.begin(), 746 std::find(enabled_state_observer_list_.begin(),
749 enabled_state_observer_list_.end(), listener); 747 enabled_state_observer_list_.end(), listener);
750 if (it != enabled_state_observer_list_.end()) 748 if (it != enabled_state_observer_list_.end())
751 enabled_state_observer_list_.erase(it); 749 enabled_state_observer_list_.erase(it);
752 } 750 }
753 751
754 bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const { 752 bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const {
755 AutoLock lock(lock_); 753 AutoLock observer_list_lock(observer_list_lock_);
756 return ContainsValue(enabled_state_observer_list_, listener); 754 return ContainsValue(enabled_state_observer_list_, listener);
757 } 755 }
758 756
759 TraceLogStatus TraceLog::GetStatus() const { 757 TraceLogStatus TraceLog::GetStatus() const {
760 AutoLock lock(lock_); 758 AutoLock lock(lock_);
761 TraceLogStatus result; 759 TraceLogStatus result;
762 result.event_capacity = static_cast<uint32_t>(logged_events_->Capacity()); 760 result.event_capacity = static_cast<uint32_t>(logged_events_->Capacity());
763 result.event_count = static_cast<uint32_t>(logged_events_->Size()); 761 result.event_count = static_cast<uint32_t>(logged_events_->Size());
764 return result; 762 return result;
765 } 763 }
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
1742 } 1740 }
1743 1741
1744 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { 1742 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
1745 if (*category_group_enabled_) { 1743 if (*category_group_enabled_) {
1746 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, 1744 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_,
1747 event_handle_); 1745 event_handle_);
1748 } 1746 }
1749 } 1747 }
1750 1748
1751 } // namespace trace_event_internal 1749 } // namespace trace_event_internal
OLDNEW
« base/trace_event/trace_event_unittest.cc ('K') | « base/trace_event/trace_log.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698