Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 return false; | 853 return false; |
| 854 | 854 |
| 855 // TODO(lawrencewu): Convert the API for CreateFieldTrial to take | 855 // TODO(lawrencewu): Convert the API for CreateFieldTrial to take |
| 856 // StringPieces. | 856 // StringPieces. |
| 857 FieldTrial* trial = | 857 FieldTrial* trial = |
| 858 CreateFieldTrial(trial_name.as_string(), group_name.as_string()); | 858 CreateFieldTrial(trial_name.as_string(), group_name.as_string()); |
| 859 | 859 |
| 860 // If we failed to create the field trial, crash with debug info. | 860 // If we failed to create the field trial, crash with debug info. |
| 861 // TODO(665129): Remove this when the crash is resolved. | 861 // TODO(665129): Remove this when the crash is resolved. |
| 862 if (!trial) { | 862 if (!trial) { |
| 863 const size_t buf_size = 100; | |
|
Alexei Svitkine (slow)
2016/11/21 16:26:33
Nit: constexpr
lawrencewu
2016/11/21 20:08:15
Done.
| |
| 863 std::string trial_name_string = trial_name.as_string(); | 864 std::string trial_name_string = trial_name.as_string(); |
| 865 char trial_name_c_str[buf_size]; | |
|
Alexei Svitkine (slow)
2016/11/21 16:26:33
= {0};
On all of these.
Actually, you only reall
lawrencewu
2016/11/21 20:08:15
Done.
| |
| 866 strncpy(trial_name_c_str, trial_name_string.c_str(), buf_size); | |
|
Alexei Svitkine (slow)
2016/11/21 16:26:32
Use strlcpy() instead.
strncpy will not terminate
lawrencewu
2016/11/21 20:08:15
Done.
| |
| 867 | |
| 864 std::string group_name_string = group_name.as_string(); | 868 std::string group_name_string = group_name.as_string(); |
| 869 char group_name_c_str[buf_size]; | |
|
Alexei Svitkine (slow)
2016/11/21 16:26:32
Nit: Suggest moving all the buffer declarations to
lawrencewu
2016/11/21 20:08:15
Done.
| |
| 870 strncpy(group_name_c_str, group_name_string.c_str(), buf_size); | |
| 871 | |
| 865 FieldTrial* existing_field_trial = | 872 FieldTrial* existing_field_trial = |
| 866 FieldTrialList::Find(trial_name_string); | 873 FieldTrialList::Find(trial_name_string); |
| 867 if (existing_field_trial) | 874 if (existing_field_trial) { |
| 868 debug::Alias(existing_field_trial->group_name_internal().c_str()); | 875 std::string existing_group_name_string = |
| 869 debug::Alias(trial_name_string.c_str()); | 876 existing_field_trial->group_name_internal(); |
| 870 debug::Alias(group_name_string.c_str()); | 877 char existing_group_name_c_str[buf_size]; |
|
Alexei Svitkine (slow)
2016/11/21 16:26:32
This will go out of scope when we hit the crash an
lawrencewu
2016/11/21 20:08:15
Done.
| |
| 878 strncpy(existing_group_name_c_str, group_name_string.c_str(), buf_size); | |
| 879 debug::Alias(existing_group_name_c_str); | |
| 880 } | |
| 881 debug::Alias(trial_name_c_str); | |
| 882 debug::Alias(group_name_c_str); | |
| 871 CHECK(!trial_name_string.empty()); | 883 CHECK(!trial_name_string.empty()); |
| 872 CHECK(!group_name_string.empty()); | 884 CHECK(!group_name_string.empty()); |
| 873 CHECK_EQ(existing_field_trial->group_name_internal(), | 885 CHECK_EQ(existing_field_trial->group_name_internal(), |
| 874 group_name.as_string()); | 886 group_name.as_string()); |
| 875 return false; | 887 return false; |
| 876 } | 888 } |
| 877 | 889 |
| 878 trial->ref_ = ref; | 890 trial->ref_ = ref; |
| 879 if (entry->activated) { | 891 if (entry->activated) { |
| 880 // Call |group()| to mark the trial as "used" and notify observers, if | 892 // Call |group()| to mark the trial as "used" and notify observers, if |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 // Set |readonly_allocator_handle_| so we can pass it to be inherited and | 925 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
| 914 // via the command line. | 926 // via the command line. |
| 915 global_->readonly_allocator_handle_ = | 927 global_->readonly_allocator_handle_ = |
| 916 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 928 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); |
| 917 #endif | 929 #endif |
| 918 } | 930 } |
| 919 #endif | 931 #endif |
| 920 | 932 |
| 921 // static | 933 // static |
| 922 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { | 934 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { |
| 935 // In order to debug the crash where two field trials with the same name but | |
| 936 // different groups get added to the allocator, let's try to get the stack | |
| 937 // frame where the second duplicate gets added here as well as the trial/group | |
| 938 // names. | |
| 939 // TODO(665129): Remove this code once the bug has been fixed. | |
| 940 FieldTrial* possible_duplicate = | |
| 941 global_->PreLockedFind(field_trial->trial_name()); | |
|
Alexei Svitkine (slow)
2016/11/21 16:26:32
Wouldn't this find the same |field_trial| object a
lawrencewu
2016/11/21 20:08:15
Looks like that was what was causing the crash aft
| |
| 942 if (possible_duplicate) { | |
| 943 const size_t buf_size = 100; | |
| 944 | |
| 945 std::string trial_name = field_trial->trial_name(); | |
| 946 char trial_name_c_str[buf_size]; | |
| 947 strncpy(trial_name_c_str, trial_name.c_str(), buf_size); | |
| 948 debug::Alias(trial_name_c_str); | |
| 949 | |
| 950 std::string existing_group_name = possible_duplicate->group_name_; | |
| 951 char existing_group_name_c_str[buf_size]; | |
| 952 strncpy(existing_group_name_c_str, existing_group_name.c_str(), buf_size); | |
| 953 debug::Alias(existing_group_name_c_str); | |
| 954 | |
| 955 std::string group_name = field_trial->group_name_; | |
| 956 char group_name_c_str[buf_size]; | |
| 957 strncpy(group_name_c_str, group_name.c_str(), buf_size); | |
| 958 debug::Alias(group_name_c_str); | |
| 959 | |
| 960 CHECK_EQ(existing_group_name, group_name); | |
| 961 } | |
| 962 | |
| 923 SharedPersistentMemoryAllocator* allocator = | 963 SharedPersistentMemoryAllocator* allocator = |
| 924 global_->field_trial_allocator_.get(); | 964 global_->field_trial_allocator_.get(); |
| 925 | 965 |
| 926 // Don't do anything if the allocator hasn't been instantiated yet. | 966 // Don't do anything if the allocator hasn't been instantiated yet. |
| 927 if (allocator == nullptr) | 967 if (allocator == nullptr) |
| 928 return; | 968 return; |
| 929 | 969 |
| 930 // Or if the allocator is read only, which means we are in a child process and | 970 // Or if the allocator is read only, which means we are in a child process and |
| 931 // shouldn't be writing to it. | 971 // shouldn't be writing to it. |
| 932 if (allocator->IsReadonly()) | 972 if (allocator->IsReadonly()) |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1015 return; | 1055 return; |
| 1016 } | 1056 } |
| 1017 AutoLock auto_lock(global_->lock_); | 1057 AutoLock auto_lock(global_->lock_); |
| 1018 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1058 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 1019 trial->AddRef(); | 1059 trial->AddRef(); |
| 1020 trial->SetTrialRegistered(); | 1060 trial->SetTrialRegistered(); |
| 1021 global_->registered_[trial->trial_name()] = trial; | 1061 global_->registered_[trial->trial_name()] = trial; |
| 1022 } | 1062 } |
| 1023 | 1063 |
| 1024 } // namespace base | 1064 } // namespace base |
| OLD | NEW |