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

Side by Side Diff: base/metrics/field_trial.cc

Issue 2453933004: Fix deadlock issue with AllStatesToString (Closed)
Patch Set: turn flag back off Created 4 years, 1 month 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/metrics/field_trial.h" 5 #include "base/metrics/field_trial.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/base_switches.h" 10 #include "base/base_switches.h"
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { 327 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) {
328 group_ = number; 328 group_ = number;
329 if (group_name.empty()) 329 if (group_name.empty())
330 StringAppendF(&group_name_, "%d", group_); 330 StringAppendF(&group_name_, "%d", group_);
331 else 331 else
332 group_name_ = group_name; 332 group_name_ = group_name;
333 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; 333 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_;
334 } 334 }
335 335
336 void FieldTrial::FinalizeGroupChoice() { 336 void FieldTrial::FinalizeGroupChoice() {
337 FinalizeGroupChoiceImpl(false);
338 }
339
340 void FieldTrial::FinalizeGroupChoiceImpl(bool is_locked) {
337 if (group_ != kNotFinalized) 341 if (group_ != kNotFinalized)
338 return; 342 return;
339 accumulated_group_probability_ = divisor_; 343 accumulated_group_probability_ = divisor_;
340 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not 344 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not
341 // finalized. 345 // finalized.
342 DCHECK(!forced_); 346 DCHECK(!forced_);
343 SetGroupChoice(default_group_name_, kDefaultGroupNumber); 347 SetGroupChoice(default_group_name_, kDefaultGroupNumber);
344 348
345 // Add the field trial to shared memory. 349 // Add the field trial to shared memory.
346 if (kUseSharedMemoryForFieldTrials) 350 if (kUseSharedMemoryForFieldTrials)
347 FieldTrialList::OnGroupFinalized(this); 351 FieldTrialList::OnGroupFinalized(is_locked, this);
348 } 352 }
349 353
350 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { 354 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const {
351 if (!group_reported_ || !enable_field_trial_) 355 if (!group_reported_ || !enable_field_trial_)
352 return false; 356 return false;
353 DCHECK_NE(group_, kNotFinalized); 357 DCHECK_NE(group_, kNotFinalized);
354 active_group->trial_name = trial_name_; 358 active_group->trial_name = trial_name_;
355 active_group->group_name = group_name_; 359 active_group->group_name = group_name_;
356 return true; 360 return true;
357 } 361 }
358 362
359 bool FieldTrial::GetState(State* field_trial_state) { 363 bool FieldTrial::GetState(State* field_trial_state) {
360 if (!enable_field_trial_) 364 if (!enable_field_trial_)
361 return false; 365 return false;
362 FinalizeGroupChoice(); 366 FinalizeGroupChoice();
363 field_trial_state->trial_name = trial_name_; 367 field_trial_state->trial_name = trial_name_;
364 field_trial_state->group_name = group_name_; 368 field_trial_state->group_name = group_name_;
365 field_trial_state->activated = group_reported_; 369 field_trial_state->activated = group_reported_;
366 return true; 370 return true;
367 } 371 }
368 372
373 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) {
374 if (!enable_field_trial_)
375 return false;
376 FinalizeGroupChoiceImpl(true);
377 field_trial_state->trial_name = trial_name_;
378 field_trial_state->group_name = group_name_;
379 field_trial_state->activated = group_reported_;
380 return true;
381 }
382
369 //------------------------------------------------------------------------------ 383 //------------------------------------------------------------------------------
370 // FieldTrialList methods and members. 384 // FieldTrialList methods and members.
371 385
372 // static 386 // static
373 FieldTrialList* FieldTrialList::global_ = NULL; 387 FieldTrialList* FieldTrialList::global_ = NULL;
374 388
375 // static 389 // static
376 bool FieldTrialList::used_without_global_ = false; 390 bool FieldTrialList::used_without_global_ = false;
377 391
378 FieldTrialList::Observer::~Observer() { 392 FieldTrialList::Observer::~Observer() {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 } 553 }
540 554
541 // static 555 // static
542 void FieldTrialList::AllStatesToString(std::string* output) { 556 void FieldTrialList::AllStatesToString(std::string* output) {
543 if (!global_) 557 if (!global_)
544 return; 558 return;
545 AutoLock auto_lock(global_->lock_); 559 AutoLock auto_lock(global_->lock_);
546 560
547 for (const auto& registered : global_->registered_) { 561 for (const auto& registered : global_->registered_) {
548 FieldTrial::State trial; 562 FieldTrial::State trial;
549 if (!registered.second->GetState(&trial)) 563 if (!registered.second->GetStateWhileLocked(&trial))
550 continue; 564 continue;
551 DCHECK_EQ(std::string::npos, 565 DCHECK_EQ(std::string::npos,
552 trial.trial_name.find(kPersistentStringSeparator)); 566 trial.trial_name.find(kPersistentStringSeparator));
553 DCHECK_EQ(std::string::npos, 567 DCHECK_EQ(std::string::npos,
554 trial.group_name.find(kPersistentStringSeparator)); 568 trial.group_name.find(kPersistentStringSeparator));
555 if (trial.activated) 569 if (trial.activated)
556 output->append(1, kActivationMarker); 570 output->append(1, kActivationMarker);
557 trial.trial_name.AppendToString(output); 571 trial.trial_name.AppendToString(output);
558 output->append(1, kPersistentStringSeparator); 572 output->append(1, kPersistentStringSeparator);
559 trial.group_name.AppendToString(output); 573 trial.group_name.AppendToString(output);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 } 678 }
665 679
666 #if defined(OS_WIN) 680 #if defined(OS_WIN)
667 // static 681 // static
668 void FieldTrialList::AppendFieldTrialHandleIfNeeded( 682 void FieldTrialList::AppendFieldTrialHandleIfNeeded(
669 HandlesToInheritVector* handles) { 683 HandlesToInheritVector* handles) {
670 if (!global_) 684 if (!global_)
671 return; 685 return;
672 if (kUseSharedMemoryForFieldTrials) { 686 if (kUseSharedMemoryForFieldTrials) {
673 InstantiateFieldTrialAllocatorIfNeeded(); 687 InstantiateFieldTrialAllocatorIfNeeded();
674 if (global_->readonly_allocator_handle_) 688 if (global_ && global_->readonly_allocator_handle_)
Alexei Svitkine (slow) 2016/10/28 18:57:34 There's already an early return on line 684.
lawrencewu 2016/10/31 18:59:25 Fixed.
675 handles->push_back(global_->readonly_allocator_handle_); 689 handles->push_back(global_->readonly_allocator_handle_);
676 } 690 }
677 } 691 }
678 #endif 692 #endif
679 693
680 // static 694 // static
681 void FieldTrialList::CopyFieldTrialStateToFlags( 695 void FieldTrialList::CopyFieldTrialStateToFlags(
682 const char* field_trial_handle_switch, 696 const char* field_trial_handle_switch,
683 CommandLine* cmd_line) { 697 CommandLine* cmd_line) {
684 #if defined(OS_WIN) 698 #if defined(OS_WIN)
685 // Use shared memory to pass the state if the feature is enabled, otherwise 699 // Use shared memory to pass the state if the feature is enabled, otherwise
686 // fallback to passing it via the command line as a string. 700 // fallback to passing it via the command line as a string.
687 if (kUseSharedMemoryForFieldTrials) { 701 if (kUseSharedMemoryForFieldTrials) {
688 InstantiateFieldTrialAllocatorIfNeeded(); 702 InstantiateFieldTrialAllocatorIfNeeded();
689 // If the readonly handle didn't get duplicated properly, then fallback to 703 // If the readonly handle didn't get duplicated properly, then fallback to
690 // original behavior. 704 // original behavior.
691 if (!global_->readonly_allocator_handle_) { 705 if (!global_ || !global_->readonly_allocator_handle_) {
Alexei Svitkine (slow) 2016/10/28 18:57:34 Can we instead fix the browser test to have a Fiel
lawrencewu 2016/10/31 18:59:25 As we discussed, I moved the check for global to t
692 AddForceFieldTrialsFlag(cmd_line); 706 AddForceFieldTrialsFlag(cmd_line);
693 return; 707 return;
694 } 708 }
695 709
696 // HANDLE is just typedef'd to void *. We basically cast the handle into an 710 // HANDLE is just typedef'd to void *. We basically cast the handle into an
697 // int (uintptr_t, to be exact), stringify the int, and pass it as a 711 // int (uintptr_t, to be exact), stringify the int, and pass it as a
698 // command-line flag. The child process will do the reverse conversions to 712 // command-line flag. The child process will do the reverse conversions to
699 // retrieve the handle. See http://stackoverflow.com/a/153077 713 // retrieve the handle. See http://stackoverflow.com/a/153077
700 auto uintptr_handle = 714 auto uintptr_handle =
701 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); 715 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 } 762 }
749 763
750 // static 764 // static
751 void FieldTrialList::RemoveObserver(Observer* observer) { 765 void FieldTrialList::RemoveObserver(Observer* observer) {
752 if (!global_) 766 if (!global_)
753 return; 767 return;
754 global_->observer_list_->RemoveObserver(observer); 768 global_->observer_list_->RemoveObserver(observer);
755 } 769 }
756 770
757 // static 771 // static
758 void FieldTrialList::OnGroupFinalized(FieldTrial* field_trial) { 772 void FieldTrialList::OnGroupFinalized(bool is_locked, FieldTrial* field_trial) {
759 if (!global_) 773 if (!global_)
760 return; 774 return;
761 AutoLock auto_lock(global_->lock_); 775 if (is_locked) {
762 AddToAllocatorWhileLocked(field_trial); 776 AddToAllocatorWhileLocked(field_trial);
777 } else {
778 AutoLock auto_lock(global_->lock_);
779 AddToAllocatorWhileLocked(field_trial);
780 }
763 } 781 }
764 782
765 // static 783 // static
766 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { 784 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) {
767 if (!global_) 785 if (!global_)
768 return; 786 return;
769 787
770 { 788 {
771 AutoLock auto_lock(global_->lock_); 789 AutoLock auto_lock(global_->lock_);
772 if (field_trial->group_reported_) 790 if (field_trial->group_reported_)
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 return; 962 return;
945 } 963 }
946 AutoLock auto_lock(global_->lock_); 964 AutoLock auto_lock(global_->lock_);
947 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 965 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
948 trial->AddRef(); 966 trial->AddRef();
949 trial->SetTrialRegistered(); 967 trial->SetTrialRegistered();
950 global_->registered_[trial->trial_name()] = trial; 968 global_->registered_[trial->trial_name()] = trial;
951 } 969 }
952 970
953 } // namespace base 971 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698