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

Side by Side Diff: client/settings.cc

Issue 1392953002: Don’t log an error when creating a new crash report database (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Add missing be Created 5 years, 2 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
« no previous file with comments | « client/settings.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 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 64
65 Settings::Settings(const base::FilePath& file_path) 65 Settings::Settings(const base::FilePath& file_path)
66 : file_path_(file_path), 66 : file_path_(file_path),
67 initialized_() { 67 initialized_() {
68 } 68 }
69 69
70 Settings::~Settings() { 70 Settings::~Settings() {
71 } 71 }
72 72
73 bool Settings::Initialize() { 73 bool Settings::Initialize() {
74 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); 74 initialized_.set_invalid();
75 75
76 Data settings; 76 Data settings;
77 if (!OpenForWritingAndReadSettings(&settings).is_valid()) 77 if (!OpenForWritingAndReadSettings(&settings).is_valid())
78 return false; 78 return false;
79 79
80 INITIALIZATION_STATE_SET_VALID(initialized_); 80 initialized_.set_valid();
81 return true; 81 return true;
82 } 82 }
83 83
84 bool Settings::GetClientID(UUID* client_id) { 84 bool Settings::GetClientID(UUID* client_id) {
85 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 85 DCHECK(initialized_.is_valid());
86 86
87 Data settings; 87 Data settings;
88 if (!OpenAndReadSettings(&settings)) 88 if (!OpenAndReadSettings(&settings))
89 return false; 89 return false;
90 90
91 *client_id = settings.client_id; 91 *client_id = settings.client_id;
92 return true; 92 return true;
93 } 93 }
94 94
95 bool Settings::GetUploadsEnabled(bool* enabled) { 95 bool Settings::GetUploadsEnabled(bool* enabled) {
96 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 96 DCHECK(initialized_.is_valid());
97 97
98 Data settings; 98 Data settings;
99 if (!OpenAndReadSettings(&settings)) 99 if (!OpenAndReadSettings(&settings))
100 return false; 100 return false;
101 101
102 *enabled = (settings.options & Data::Options::kUploadsEnabled) != 0; 102 *enabled = (settings.options & Data::Options::kUploadsEnabled) != 0;
103 return true; 103 return true;
104 } 104 }
105 105
106 bool Settings::SetUploadsEnabled(bool enabled) { 106 bool Settings::SetUploadsEnabled(bool enabled) {
107 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 107 DCHECK(initialized_.is_valid());
108 108
109 Data settings; 109 Data settings;
110 ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings); 110 ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings);
111 if (!handle.is_valid()) 111 if (!handle.is_valid())
112 return false; 112 return false;
113 113
114 if (enabled) 114 if (enabled)
115 settings.options |= Data::Options::kUploadsEnabled; 115 settings.options |= Data::Options::kUploadsEnabled;
116 else 116 else
117 settings.options &= ~Data::Options::kUploadsEnabled; 117 settings.options &= ~Data::Options::kUploadsEnabled;
118 118
119 return WriteSettings(handle.get(), settings); 119 return WriteSettings(handle.get(), settings);
120 } 120 }
121 121
122 bool Settings::GetLastUploadAttemptTime(time_t* time) { 122 bool Settings::GetLastUploadAttemptTime(time_t* time) {
123 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 123 DCHECK(initialized_.is_valid());
124 124
125 Data settings; 125 Data settings;
126 if (!OpenAndReadSettings(&settings)) 126 if (!OpenAndReadSettings(&settings))
127 return false; 127 return false;
128 128
129 *time = InRangeCast<time_t>(settings.last_upload_attempt_time, 129 *time = InRangeCast<time_t>(settings.last_upload_attempt_time,
130 std::numeric_limits<time_t>::max()); 130 std::numeric_limits<time_t>::max());
131 return true; 131 return true;
132 } 132 }
133 133
134 bool Settings::SetLastUploadAttemptTime(time_t time) { 134 bool Settings::SetLastUploadAttemptTime(time_t time) {
135 INITIALIZATION_STATE_DCHECK_VALID(initialized_); 135 DCHECK(initialized_.is_valid());
136 136
137 Data settings; 137 Data settings;
138 ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings); 138 ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings);
139 if (!handle.is_valid()) 139 if (!handle.is_valid())
140 return false; 140 return false;
141 141
142 settings.last_upload_attempt_time = InRangeCast<uint64_t>(time, 0); 142 settings.last_upload_attempt_time = InRangeCast<uint64_t>(time, 0);
143 143
144 return WriteSettings(handle.get(), settings); 144 return WriteSettings(handle.get(), settings);
145 } 145 }
146 146
147 // static 147 // static
148 Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle( 148 Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle(
149 FileHandle file, 149 FileHandle file,
150 FileLocking locking) { 150 FileLocking locking) {
151 ScopedFileHandle scoped(file); 151 ScopedFileHandle scoped(file);
152 if (scoped.is_valid()) { 152 if (scoped.is_valid()) {
153 if (!LoggingLockFile(scoped.get(), locking)) 153 if (!LoggingLockFile(scoped.get(), locking))
154 scoped.reset(); 154 scoped.reset();
155 } 155 }
156 return ScopedLockedFileHandle(scoped.release()); 156 return ScopedLockedFileHandle(scoped.release());
157 } 157 }
158 158
159 Settings::ScopedLockedFileHandle Settings::OpenForReading() { 159 Settings::ScopedLockedFileHandle Settings::OpenForReading() {
160 return MakeScopedLockedFileHandle(LoggingOpenFileForRead(file_path()), 160 return MakeScopedLockedFileHandle(LoggingOpenFileForRead(file_path()),
161 FileLocking::kShared); 161 FileLocking::kShared);
162 } 162 }
163 163
164 Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting() { 164 Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting(
165 return MakeScopedLockedFileHandle( 165 FileWriteMode mode, bool log_open_error) {
166 LoggingOpenFileForReadAndWrite(file_path(), 166 DCHECK(mode != FileWriteMode::kTruncateOrCreate);
167 FileWriteMode::kReuseOrCreate, 167
168 FilePermissions::kWorldReadable), 168 FileHandle handle;
169 FileLocking::kExclusive); 169 if (log_open_error) {
170 handle = LoggingOpenFileForReadAndWrite(
171 file_path(), mode, FilePermissions::kWorldReadable);
172 } else {
173 handle = OpenFileForReadAndWrite(
174 file_path(), mode, FilePermissions::kWorldReadable);
175 }
176
177 return MakeScopedLockedFileHandle(handle, FileLocking::kExclusive);
170 } 178 }
171 179
172 bool Settings::OpenAndReadSettings(Data* out_data) { 180 bool Settings::OpenAndReadSettings(Data* out_data) {
173 ScopedLockedFileHandle handle = OpenForReading(); 181 ScopedLockedFileHandle handle = OpenForReading();
174 if (!handle.is_valid()) 182 if (!handle.is_valid())
175 return false; 183 return false;
176 184
177 if (ReadSettings(handle.get(), out_data)) 185 if (ReadSettings(handle.get(), out_data, true))
178 return true; 186 return true;
179 187
180 // The settings file is corrupt, so reinitialize it. 188 // The settings file is corrupt, so reinitialize it.
181 handle.reset(); 189 handle.reset();
182 190
183 // The settings failed to be read, so re-initialize them. 191 // The settings failed to be read, so re-initialize them.
184 return RecoverSettings(kInvalidFileHandle, out_data); 192 return RecoverSettings(kInvalidFileHandle, out_data);
185 } 193 }
186 194
187 Settings::ScopedLockedFileHandle Settings::OpenForWritingAndReadSettings( 195 Settings::ScopedLockedFileHandle Settings::OpenForWritingAndReadSettings(
188 Data* out_data) { 196 Data* out_data) {
189 ScopedLockedFileHandle handle = OpenForReadingAndWriting(); 197 ScopedLockedFileHandle handle;
198 bool created = false;
199 if (!initialized_.is_valid()) {
200 // If this object is initializing, it hasn’t seen a settings file already,
201 // so go easy on errors. Creating a new settings file for the first time
202 // shouldn’t spew log messages.
203 //
204 // First, try to use an existing settings file.
205 handle = OpenForReadingAndWriting(FileWriteMode::kReuseOrFail, false);
206
207 if (!handle.is_valid()) {
208 // Create a new settings file if it didn’t already exist.
209 handle = OpenForReadingAndWriting(FileWriteMode::kCreateOrFail, false);
210
211 if (handle.is_valid()) {
212 created = true;
213 }
214
215 // There may have been a race to create the file, and something else may
216 // have won. There will be one more attempt to try to open or create the
217 // file below.
218 }
219 }
220
221 if (!handle.is_valid()) {
222 // Either the object is initialized, meaning it’s already seen a valid
223 // settings file, or the object is initializing and none of the above
224 // attempts to create the settings file succeeded. Either way, this is the
225 // last chance for success, so if this fails, log a message.
226 handle = OpenForReadingAndWriting(FileWriteMode::kReuseOrCreate, true);
227 }
228
190 if (!handle.is_valid()) 229 if (!handle.is_valid())
191 return ScopedLockedFileHandle(); 230 return ScopedLockedFileHandle();
192 231
193 if (!ReadSettings(handle.get(), out_data)) { 232 // Attempt reading the settings even if the file is known to have just been
233 // created. The file-create and file-lock operations don’t occur atomically,
234 // and something else may have written the settings before this invocation
235 // took the lock. If the settings file was definitely just created, though,
236 // don’t log any read errors. The expected non-race behavior in this case is a
237 // zero-length read, with ReadSettings() failing.
238 if (!ReadSettings(handle.get(), out_data, !created)) {
194 if (!RecoverSettings(handle.get(), out_data)) 239 if (!RecoverSettings(handle.get(), out_data))
195 return ScopedLockedFileHandle(); 240 return ScopedLockedFileHandle();
196 } 241 }
197 242
198 return handle.Pass(); 243 return handle.Pass();
199 } 244 }
200 245
201 bool Settings::ReadSettings(FileHandle handle, Data* out_data) { 246 bool Settings::ReadSettings(FileHandle handle,
247 Data* out_data,
248 bool log_read_error) {
202 if (LoggingSeekFile(handle, 0, SEEK_SET) != 0) 249 if (LoggingSeekFile(handle, 0, SEEK_SET) != 0)
203 return false; 250 return false;
204 251
205 if (!LoggingReadFile(handle, out_data, sizeof(*out_data))) 252 bool read_result;
253 if (log_read_error)
254 read_result = LoggingReadFile(handle, out_data, sizeof(*out_data));
255 else
256 read_result = ReadFile(handle, out_data, sizeof(*out_data));
257
258 if (!read_result)
206 return false; 259 return false;
207 260
208 if (out_data->magic != Data::kSettingsMagic) { 261 if (out_data->magic != Data::kSettingsMagic) {
209 LOG(ERROR) << "Settings magic is not " << Data::kSettingsMagic; 262 LOG(ERROR) << "Settings magic is not " << Data::kSettingsMagic;
210 return false; 263 return false;
211 } 264 }
212 265
213 if (out_data->version != Data::kSettingsVersion) { 266 if (out_data->version != Data::kSettingsVersion) {
214 LOG(ERROR) << "Settings version is not " << Data::kSettingsVersion; 267 LOG(ERROR) << "Settings version is not " << Data::kSettingsVersion;
215 return false; 268 return false;
216 } 269 }
217 270
218 return true; 271 return true;
219 } 272 }
220 273
221 bool Settings::WriteSettings(FileHandle handle, const Data& data) { 274 bool Settings::WriteSettings(FileHandle handle, const Data& data) {
222 if (LoggingSeekFile(handle, 0, SEEK_SET) != 0) 275 if (LoggingSeekFile(handle, 0, SEEK_SET) != 0)
223 return false; 276 return false;
224 277
225 if (!LoggingTruncateFile(handle)) 278 if (!LoggingTruncateFile(handle))
226 return false; 279 return false;
227 280
228 return LoggingWriteFile(handle, &data, sizeof(Data)); 281 return LoggingWriteFile(handle, &data, sizeof(Data));
229 } 282 }
230 283
231 bool Settings::RecoverSettings(FileHandle handle, Data* out_data) { 284 bool Settings::RecoverSettings(FileHandle handle, Data* out_data) {
232 ScopedLockedFileHandle scoped_handle; 285 ScopedLockedFileHandle scoped_handle;
233 if (handle == kInvalidFileHandle) { 286 if (handle == kInvalidFileHandle) {
234 scoped_handle = OpenForReadingAndWriting(); 287 scoped_handle =
288 OpenForReadingAndWriting(FileWriteMode::kReuseOrCreate, true);
235 handle = scoped_handle.get(); 289 handle = scoped_handle.get();
236 290
237 // Test if the file has already been recovered now that the exclusive lock 291 // Test if the file has already been recovered now that the exclusive lock
238 // is held. 292 // is held.
239 if (ReadSettings(handle, out_data)) 293 if (ReadSettings(handle, out_data, true))
240 return true; 294 return true;
241 } 295 }
242 296
243 if (handle == kInvalidFileHandle) { 297 if (handle == kInvalidFileHandle) {
244 LOG(ERROR) << "Invalid file handle"; 298 LOG(ERROR) << "Invalid file handle";
245 return false; 299 return false;
246 } 300 }
247 301
248 if (!InitializeSettings(handle)) 302 if (!InitializeSettings(handle))
249 return false; 303 return false;
250 304
251 return ReadSettings(handle, out_data); 305 return ReadSettings(handle, out_data, true);
252 } 306 }
253 307
254 bool Settings::InitializeSettings(FileHandle handle) { 308 bool Settings::InitializeSettings(FileHandle handle) {
255 Data settings; 309 Data settings;
256 if (!settings.client_id.InitializeWithNew()) 310 if (!settings.client_id.InitializeWithNew())
257 return false; 311 return false;
258 312
259 return WriteSettings(handle, settings); 313 return WriteSettings(handle, settings);
260 } 314 }
261 315
262 } // namespace crashpad 316 } // namespace crashpad
OLDNEW
« no previous file with comments | « client/settings.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698