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

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

Issue 2511413002: Add debug info for field trial allocation crash (Closed)
Patch Set: address comments Created 4 years 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
« no previous file with comments | « base/metrics/field_trial.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 177
178 void AddForceFieldTrialsFlag(CommandLine* cmd_line) { 178 void AddForceFieldTrialsFlag(CommandLine* cmd_line) {
179 std::string field_trial_states; 179 std::string field_trial_states;
180 FieldTrialList::AllStatesToString(&field_trial_states); 180 FieldTrialList::AllStatesToString(&field_trial_states);
181 if (!field_trial_states.empty()) { 181 if (!field_trial_states.empty()) {
182 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials, 182 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials,
183 field_trial_states); 183 field_trial_states);
184 } 184 }
185 } 185 }
186 186
187 // In order to debug the crash where two field trials with the same name but
188 // different groups get added to the allocator, let's try to get the stack
189 // frame where the second duplicate gets added here as well as the trial/group
190 // names by going through the allocator and checking if a trial with the same
191 // name already exists.
192 void CheckAllocatorForTrial(FieldTrialList::FieldTrialAllocator* allocator,
193 const std::string& trial_name,
194 const std::string& group_name) {
195 FieldTrialList::FieldTrialAllocator::Iterator iter(allocator);
196 FieldTrial::FieldTrialRef ref;
197 while ((ref = iter.GetNextOfType(kFieldTrialType)) !=
198 FieldTrialList::FieldTrialAllocator::kReferenceNull) {
199 const FieldTrialEntry* entry =
200 allocator->GetAsObject<const FieldTrialEntry>(ref, kFieldTrialType);
201
202 StringPiece trial_name_to_check;
203 StringPiece group_name_to_check;
204 if (!entry->GetTrialAndGroupName(&trial_name_to_check,
205 &group_name_to_check)) {
206 CHECK(false);
207 }
208
209 if (trial_name_to_check.as_string() == trial_name) {
210 constexpr size_t buf_size = 100;
211
212 char trial_name_c_str[buf_size];
213 char group_name_c_str[buf_size];
214 char existing_group_name_c_str[buf_size];
215
216 strlcpy(trial_name_c_str, trial_name.c_str(), buf_size);
217 strlcpy(group_name_c_str, group_name.c_str(), buf_size);
218 strlcpy(existing_group_name_c_str,
219 group_name_to_check.as_string().c_str(), buf_size);
brucedawson 2016/11/22 17:55:24 Unfortunately, calling as_string() is exactly as e
Alexei Svitkine (slow) 2016/11/22 18:49:30 +1 You should be able to strlcpy() from the Strin
220
221 debug::Alias(trial_name_c_str);
222 debug::Alias(group_name_c_str);
223 debug::Alias(existing_group_name_c_str);
224 CHECK_EQ(group_name_to_check.as_string(), group_name);
225 }
226 }
227 }
228
187 #if defined(OS_WIN) 229 #if defined(OS_WIN)
188 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { 230 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) {
189 HANDLE src = allocator->shared_memory()->handle().GetHandle(); 231 HANDLE src = allocator->shared_memory()->handle().GetHandle();
190 ProcessHandle process = GetCurrentProcess(); 232 ProcessHandle process = GetCurrentProcess();
191 DWORD access = SECTION_MAP_READ | SECTION_QUERY; 233 DWORD access = SECTION_MAP_READ | SECTION_QUERY;
192 HANDLE dst; 234 HANDLE dst;
193 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) 235 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0))
194 return nullptr; 236 return nullptr;
195 return dst; 237 return dst;
196 } 238 }
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 return false; 895 return false;
854 896
855 // TODO(lawrencewu): Convert the API for CreateFieldTrial to take 897 // TODO(lawrencewu): Convert the API for CreateFieldTrial to take
856 // StringPieces. 898 // StringPieces.
857 FieldTrial* trial = 899 FieldTrial* trial =
858 CreateFieldTrial(trial_name.as_string(), group_name.as_string()); 900 CreateFieldTrial(trial_name.as_string(), group_name.as_string());
859 901
860 // If we failed to create the field trial, crash with debug info. 902 // If we failed to create the field trial, crash with debug info.
861 // TODO(665129): Remove this when the crash is resolved. 903 // TODO(665129): Remove this when the crash is resolved.
862 if (!trial) { 904 if (!trial) {
905 constexpr size_t buf_size = 100;
906 char trial_name_c_str[buf_size] = {0};
907 char group_name_c_str[buf_size] = {0};
908 char existing_group_name_c_str[buf_size] = {0};
909
910 // Copy the names over to the stack.
863 std::string trial_name_string = trial_name.as_string(); 911 std::string trial_name_string = trial_name.as_string();
912 strlcpy(trial_name_c_str, trial_name_string.c_str(), buf_size);
864 std::string group_name_string = group_name.as_string(); 913 std::string group_name_string = group_name.as_string();
914 strlcpy(group_name_c_str, group_name_string.c_str(), buf_size);
915
916 // Alias the trial and group name.
917 debug::Alias(trial_name_c_str);
918 debug::Alias(group_name_c_str);
919
920 // Copy and alias the existing field trial name, if there is one.
865 FieldTrial* existing_field_trial = 921 FieldTrial* existing_field_trial =
866 FieldTrialList::Find(trial_name_string); 922 FieldTrialList::Find(trial_name_string);
867 if (existing_field_trial) 923 if (existing_field_trial) {
868 debug::Alias(existing_field_trial->group_name_internal().c_str()); 924 std::string existing_group_name_string =
869 debug::Alias(trial_name_string.c_str()); 925 existing_field_trial->group_name_internal();
870 debug::Alias(group_name_string.c_str()); 926 strlcpy(existing_group_name_c_str, group_name_string.c_str(), buf_size);
927 debug::Alias(existing_group_name_c_str);
928 }
871 CHECK(!trial_name_string.empty()); 929 CHECK(!trial_name_string.empty());
872 CHECK(!group_name_string.empty()); 930 CHECK(!group_name_string.empty());
873 CHECK_EQ(existing_field_trial->group_name_internal(), 931 CHECK_EQ(existing_field_trial->group_name_internal(),
874 group_name.as_string()); 932 group_name.as_string());
875 return false; 933 return false;
876 } 934 }
877 935
878 trial->ref_ = ref; 936 trial->ref_ = ref;
879 if (entry->activated) { 937 if (entry->activated) {
880 // Call |group()| to mark the trial as "used" and notify observers, if 938 // Call |group()| to mark the trial as "used" and notify observers, if
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 982
925 // Don't do anything if the allocator hasn't been instantiated yet. 983 // Don't do anything if the allocator hasn't been instantiated yet.
926 if (allocator == nullptr) 984 if (allocator == nullptr)
927 return; 985 return;
928 986
929 // Or if the allocator is read only, which means we are in a child process and 987 // Or if the allocator is read only, which means we are in a child process and
930 // shouldn't be writing to it. 988 // shouldn't be writing to it.
931 if (allocator->IsReadonly()) 989 if (allocator->IsReadonly())
932 return; 990 return;
933 991
992 // TODO(665129): Remove this code once the bug has been fixed.
993 CheckAllocatorForTrial(allocator, field_trial->trial_name(),
994 field_trial->group_name_internal());
995
934 FieldTrial::State trial_state; 996 FieldTrial::State trial_state;
935 if (!field_trial->GetStateWhileLocked(&trial_state)) 997 if (!field_trial->GetStateWhileLocked(&trial_state))
936 return; 998 return;
937 999
938 // Or if we've already added it. We must check after GetState since it can 1000 // Or if we've already added it. We must check after GetState since it can
939 // also add to the allocator. 1001 // also add to the allocator.
940 if (field_trial->ref_) 1002 if (field_trial->ref_)
941 return; 1003 return;
942 1004
943 Pickle pickle; 1005 Pickle pickle;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 return; 1075 return;
1014 } 1076 }
1015 AutoLock auto_lock(global_->lock_); 1077 AutoLock auto_lock(global_->lock_);
1016 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1078 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
1017 trial->AddRef(); 1079 trial->AddRef();
1018 trial->SetTrialRegistered(); 1080 trial->SetTrialRegistered();
1019 global_->registered_[trial->trial_name()] = trial; 1081 global_->registered_[trial->trial_name()] = trial;
1020 } 1082 }
1021 1083
1022 } // namespace base 1084 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/field_trial.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698