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

Side by Side Diff: chromecast/crash/linux/synchronized_minidump_manager.cc

Issue 2203123003: [Chromecast] Remove usage of nonreentrant functions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Bool error codes Created 4 years, 4 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 "chromecast/crash/linux/synchronized_minidump_manager.h" 5 #include "chromecast/crash/linux/synchronized_minidump_manager.h"
6 6
7 #include <dirent.h>
8 #include <errno.h> 7 #include <errno.h>
9 #include <fcntl.h>
10 #include <stddef.h> 8 #include <stddef.h>
11 #include <stdint.h> 9 #include <stdint.h>
12 #include <string.h> 10 #include <string.h>
13 #include <sys/file.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #include <unistd.h>
18 11
19 #include <utility> 12 #include <utility>
20 13
21 #include "base/files/dir_reader_posix.h" 14 #include "base/files/dir_reader_posix.h"
22 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
23 #include "base/logging.h" 16 #include "base/logging.h"
24 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h" 19 #include "base/strings/string_split.h"
26 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
21 #include "chromecast/base/file_utils.h"
27 #include "chromecast/base/path_utils.h" 22 #include "chromecast/base/path_utils.h"
28 #include "chromecast/base/serializers.h" 23 #include "chromecast/base/serializers.h"
29 #include "chromecast/crash/linux/dump_info.h" 24 #include "chromecast/crash/linux/dump_info.h"
30 25
31 // if |cond| is false, returns |retval|. 26 // if |cond| is false, returns |retval|.
32 #define RCHECK(cond, retval) \ 27 #define RCHECK(cond, retval) \
33 do { \ 28 do { \
34 if (!(cond)) { \ 29 if (!(cond)) { \
35 return (retval); \ 30 return (retval); \
36 } \ 31 } \
37 } while (0) 32 } while (0)
38 33
39 namespace chromecast { 34 namespace chromecast {
40 35
41 namespace { 36 namespace {
42 37
43 const mode_t kDirMode = 0770;
44 const mode_t kFileMode = 0660;
45 const char kLockfileName[] = "lockfile"; 38 const char kLockfileName[] = "lockfile";
46 const char kMetadataName[] = "metadata"; 39 const char kMetadataName[] = "metadata";
47 const char kMinidumpsDir[] = "minidumps"; 40 const char kMinidumpsDir[] = "minidumps";
48 41
49 const char kLockfileRatelimitKey[] = "ratelimit"; 42 const char kLockfileRatelimitKey[] = "ratelimit";
50 const char kLockfileRatelimitPeriodStartKey[] = "period_start"; 43 const char kLockfileRatelimitPeriodStartKey[] = "period_start";
51 const char kLockfileRatelimitPeriodDumpsKey[] = "period_dumps"; 44 const char kLockfileRatelimitPeriodDumpsKey[] = "period_dumps";
52 const std::size_t kLockfileNumRatelimitParams = 2; 45 const uint64_t kLockfileNumRatelimitParams = 2;
53 46
54 // Gets the ratelimit parameter dictionary given a deserialized |metadata|. 47 // Gets the ratelimit parameter dictionary given a deserialized |metadata|.
55 // Returns nullptr if invalid. 48 // Returns nullptr if invalid.
56 base::DictionaryValue* GetRatelimitParams(base::Value* metadata) { 49 base::DictionaryValue* GetRatelimitParams(base::Value* metadata) {
57 base::DictionaryValue* dict; 50 base::DictionaryValue* dict;
58 base::DictionaryValue* ratelimit_params; 51 base::DictionaryValue* ratelimit_params;
59 if (!metadata || !metadata->GetAsDictionary(&dict) || 52 if (!metadata || !metadata->GetAsDictionary(&dict) ||
60 !dict->GetDictionary(kLockfileRatelimitKey, &ratelimit_params)) { 53 !dict->GetDictionary(kLockfileRatelimitKey, &ratelimit_params)) {
61 return nullptr; 54 return nullptr;
62 } 55 }
63 56
64 return ratelimit_params; 57 return ratelimit_params;
65 } 58 }
66 59
67 // Returns the time of the current ratelimit period's start in |metadata|. 60 // Returns the time of the current ratelimit period's start in |metadata|.
68 // Returns (time_t)-1 if an error occurs. 61 // Returns base::Time() if an error occurs.
69 time_t GetRatelimitPeriodStart(base::Value* metadata) { 62 base::Time GetRatelimitPeriodStart(base::Value* metadata) {
70 time_t result = static_cast<time_t>(-1);
71 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); 63 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata);
72 RCHECK(ratelimit_params, result); 64 RCHECK(ratelimit_params, base::Time());
73 65
74 std::string period_start_str; 66 double seconds;
slan 2016/08/08 16:37:10 nit: init
ameyak 2016/08/08 18:00:43 Done.
75 RCHECK(ratelimit_params->GetString(kLockfileRatelimitPeriodStartKey, 67 RCHECK(
76 &period_start_str), 68 ratelimit_params->GetDouble(kLockfileRatelimitPeriodStartKey, &seconds),
77 result); 69 base::Time());
78 70
79 errno = 0; 71 // Return value of 0 indicates "not initialized", so we need to explicitly
80 result = static_cast<time_t>(strtoll(period_start_str.c_str(), nullptr, 0)); 72 // check for it and return time_t = 0 equivalent.
81 if (errno != 0) { 73 return seconds ? base::Time::FromDoubleT(seconds) : base::Time::UnixEpoch();
82 return static_cast<time_t>(-1);
83 }
84
85 return result;
86 } 74 }
87 75
88 // Sets the time of the current ratelimit period's start in |metadata| to 76 // Sets the time of the current ratelimit period's start in |metadata| to
89 // |period_start|. Returns 0 on success, < 0 on error. 77 // |period_start|. Returns true on success, false on error.
90 int SetRatelimitPeriodStart(base::Value* metadata, time_t period_start) { 78 bool SetRatelimitPeriodStart(base::Value* metadata, base::Time period_start) {
91 DCHECK_GE(period_start, 0); 79 DCHECK(!period_start.is_null());
92 80
93 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); 81 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata);
94 RCHECK(ratelimit_params, -1); 82 RCHECK(ratelimit_params, false);
95 83
96 std::string period_start_str = 84 ratelimit_params->SetDouble(kLockfileRatelimitPeriodStartKey,
97 base::StringPrintf("%lld", static_cast<long long>(period_start)); 85 period_start.ToDoubleT());
98 ratelimit_params->SetString(kLockfileRatelimitPeriodStartKey, 86 return true;
99 period_start_str);
100 return 0;
101 } 87 }
102 88
103 // Gets the number of dumps added to |metadata| in the current ratelimit 89 // Gets the number of dumps added to |metadata| in the current ratelimit
104 // period. Returns < 0 on error. 90 // period. Returns < 0 on error.
105 int GetRatelimitPeriodDumps(base::Value* metadata) { 91 int GetRatelimitPeriodDumps(base::Value* metadata) {
106 int period_dumps = -1; 92 int period_dumps = -1;
107 93
108 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); 94 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata);
109 if (!ratelimit_params || 95 if (!ratelimit_params ||
110 !ratelimit_params->GetInteger(kLockfileRatelimitPeriodDumpsKey, 96 !ratelimit_params->GetInteger(kLockfileRatelimitPeriodDumpsKey,
111 &period_dumps)) { 97 &period_dumps)) {
112 return -1; 98 return -1;
113 } 99 }
114 100
115 return period_dumps; 101 return period_dumps;
116 } 102 }
117 103
118 // Sets the current ratelimit period's number of dumps in |metadata| to 104 // Sets the current ratelimit period's number of dumps in |metadata| to
119 // |period_dumps|. Returns 0 on success, < 0 on error. 105 // |period_dumps|. Returns true on success, false on error.
120 int SetRatelimitPeriodDumps(base::Value* metadata, int period_dumps) { 106 bool SetRatelimitPeriodDumps(base::Value* metadata, int period_dumps) {
121 DCHECK_GE(period_dumps, 0); 107 DCHECK_GE(period_dumps, 0);
122 108
123 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); 109 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata);
124 RCHECK(ratelimit_params, -1); 110 RCHECK(ratelimit_params, false);
125 111
126 ratelimit_params->SetInteger(kLockfileRatelimitPeriodDumpsKey, period_dumps); 112 ratelimit_params->SetInteger(kLockfileRatelimitPeriodDumpsKey, period_dumps);
127 113
128 return 0; 114 return true;
129 } 115 }
130 116
131 // Returns true if |metadata| contains valid metadata, false otherwise. 117 // Returns true if |metadata| contains valid metadata, false otherwise.
132 bool ValidateMetadata(base::Value* metadata) { 118 bool ValidateMetadata(base::Value* metadata) {
133 RCHECK(metadata, false); 119 RCHECK(metadata, false);
134 120
135 // Validate ratelimit params 121 // Validate ratelimit params
136 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata); 122 base::DictionaryValue* ratelimit_params = GetRatelimitParams(metadata);
137 123
138 return ratelimit_params && 124 return ratelimit_params &&
139 ratelimit_params->size() == kLockfileNumRatelimitParams && 125 ratelimit_params->size() == kLockfileNumRatelimitParams &&
140 GetRatelimitPeriodStart(metadata) >= 0 && 126 !GetRatelimitPeriodStart(metadata).is_null() &&
141 GetRatelimitPeriodDumps(metadata) >= 0; 127 GetRatelimitPeriodDumps(metadata) >= 0;
142 } 128 }
143 129
144 } // namespace 130 } // namespace
145 131
146 // One day 132 // One day
147 const int SynchronizedMinidumpManager::kRatelimitPeriodSeconds = 24 * 3600; 133 const int SynchronizedMinidumpManager::kRatelimitPeriodSeconds = 24 * 3600;
148 const int SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps = 100; 134 const int SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps = 100;
149 135
150 SynchronizedMinidumpManager::SynchronizedMinidumpManager() 136 SynchronizedMinidumpManager::SynchronizedMinidumpManager()
151 : non_blocking_(false), 137 : dump_path_(GetHomePathASCII(kMinidumpsDir)),
152 dump_path_(GetHomePathASCII(kMinidumpsDir)),
153 lockfile_path_(dump_path_.Append(kLockfileName).value()), 138 lockfile_path_(dump_path_.Append(kLockfileName).value()),
154 metadata_path_(dump_path_.Append(kMetadataName).value()), 139 metadata_path_(dump_path_.Append(kMetadataName).value()),
155 lockfile_fd_(-1) { 140 lockfile_fd_(-1) {}
156 }
157 141
158 SynchronizedMinidumpManager::~SynchronizedMinidumpManager() { 142 SynchronizedMinidumpManager::~SynchronizedMinidumpManager() {
159 // Release the lock if held. 143 // Release the lock if held.
160 ReleaseLockFile(); 144 ReleaseLockFile();
161 } 145 }
162 146
163 // TODO(slan): Move some of this pruning logic to ReleaseLockFile? 147 // TODO(slan): Move some of this pruning logic to ReleaseLockFile?
164 int SynchronizedMinidumpManager::GetNumDumps(bool delete_all_dumps) { 148 int SynchronizedMinidumpManager::GetNumDumps(bool delete_all_dumps) {
165 DIR* dirp;
166 struct dirent* dptr;
167 int num_dumps = 0; 149 int num_dumps = 0;
168 150
169 // folder does not exist 151 base::DirReaderPosix reader(dump_path_.value().c_str());
170 dirp = opendir(dump_path_.value().c_str()); 152 if (!reader.IsValid()) {
171 if (dirp == NULL) {
172 LOG(ERROR) << "Unable to open directory " << dump_path_.value(); 153 LOG(ERROR) << "Unable to open directory " << dump_path_.value();
173 return 0; 154 return 0;
174 } 155 }
175 156
176 while ((dptr = readdir(dirp)) != NULL) { 157 while (reader.Next()) {
177 struct stat buf; 158 if (strcmp(reader.name(), ".") == 0 || strcmp(reader.name(), "..") == 0)
178 const std::string file_fullname = dump_path_.value() + "/" + dptr->d_name;
179 if (lstat(file_fullname.c_str(), &buf) == -1 || !S_ISREG(buf.st_mode)) {
180 // if we cannot lstat this file, it is probably bad, so skip
181 // if the file is not regular, skip
182 continue; 159 continue;
183 }
184 160
185 // 'lockfile' and 'metadata' is not counted 161 const base::FilePath dump_file(dump_path_.Append(reader.name()));
186 if (lockfile_path_ != file_fullname && metadata_path_ != file_fullname) { 162 // If file cannot be found, skip.
163 if (!base::PathExists(dump_file))
164 continue;
165
166 // Do not count |lockfile_path_| and |metadata_path_|.
167 if (lockfile_path_ != dump_file && metadata_path_ != dump_file) {
187 ++num_dumps; 168 ++num_dumps;
188 if (delete_all_dumps) { 169 if (delete_all_dumps) {
189 LOG(INFO) << "Removing " << dptr->d_name 170 LOG(INFO) << "Removing " << reader.name()
190 << "which was not in the lockfile"; 171 << "which was not in the lockfile";
191 if (remove(file_fullname.c_str()) < 0) { 172 if (!base::DeleteFile(dump_file, false)) {
192 LOG(INFO) << "remove failed. error " << strerror(errno); 173 LOG(INFO) << "remove failed. error " << strerror(errno);
slan 2016/08/08 16:37:11 PLOG
ameyak 2016/08/08 18:00:43 Done.
193 } 174 }
194 } 175 }
195 } 176 }
196 } 177 }
197 178
198 closedir(dirp);
199 return num_dumps; 179 return num_dumps;
200 } 180 }
201 181
202 int SynchronizedMinidumpManager::AcquireLockAndDoWork() { 182 bool SynchronizedMinidumpManager::AcquireLockAndDoWork() {
203 int success = -1; 183 bool success = false;
204 if (AcquireLockFile() >= 0) { 184 if (AcquireLockFile()) {
205 success = DoWork(); 185 success = DoWork();
206 ReleaseLockFile(); 186 ReleaseLockFile();
207 } 187 }
208 return success; 188 return success;
209 } 189 }
210 190
211 int SynchronizedMinidumpManager::AcquireLockFile() { 191 bool SynchronizedMinidumpManager::AcquireLockFile() {
212 DCHECK_LT(lockfile_fd_, 0); 192 DCHECK_LT(lockfile_fd_, 0);
213 // Make the directory for the minidumps if it does not exist. 193 // Make the directory for the minidumps if it does not exist.
214 if (mkdir(dump_path_.value().c_str(), kDirMode) < 0 && errno != EEXIST) { 194 base::File::Error error;
215 LOG(ERROR) << "mkdir for " << dump_path_.value().c_str() 195 if (!CreateDirectoryAndGetError(dump_path_, &error)) {
216 << " failed. error = " << strerror(errno); 196 LOG(ERROR) << "Failed to create directory " << dump_path_.value()
217 return -1; 197 << ". error = " << error;
198 return false;
218 } 199 }
219 200
220 // Open the lockfile. Create it if it does not exist. 201 // Open the lockfile. Create it if it does not exist.
221 lockfile_fd_ = open(lockfile_path_.c_str(), O_RDWR | O_CREAT, kFileMode); 202 base::File lockfile(lockfile_path_, base::File::FLAG_OPEN_ALWAYS);
222 203
223 // If opening or creating the lockfile failed, we don't want to proceed 204 // If opening or creating the lockfile failed, we don't want to proceed
224 // with dump writing for fear of exhausting up system resources. 205 // with dump writing for fear of exhausting up system resources.
225 if (lockfile_fd_ < 0) { 206 if (!lockfile.IsValid()) {
226 LOG(ERROR) << "open lockfile failed " << lockfile_path_; 207 LOG(ERROR) << "open lockfile failed " << lockfile_path_.value();
227 return -1; 208 return false;
228 } 209 }
229 210
230 // Acquire the lock on the file. Whether or not we are in non-blocking mode, 211 if ((lockfile_fd_ = OpenAndLockFile(lockfile_path_)) < 0) {
slan 2016/08/08 16:37:11 This sets lockfile_fd_ if it fails. That seems lik
ameyak 2016/08/08 18:00:43 OpenAndLockFile will return -1, which will assign
slan 2016/08/08 18:32:19 LGTM
231 // flock failure means that we did not acquire it and this method should fail.
232 int operation_mode = non_blocking_ ? (LOCK_EX | LOCK_NB) : LOCK_EX;
233 if (flock(lockfile_fd_, operation_mode) < 0) {
234 ReleaseLockFile(); 212 ReleaseLockFile();
235 LOG(INFO) << "flock lockfile failed, error = " << strerror(errno); 213 return false;
236 return -1;
237 } 214 }
238 215
239 // The lockfile is open and locked. Parse it to provide subclasses with a 216 // The lockfile is open and locked. Parse it to provide subclasses with a
240 // record of all the current dumps. 217 // record of all the current dumps.
241 if (ParseFiles() < 0) { 218 if (!ParseFiles()) {
242 LOG(ERROR) << "Lockfile did not parse correctly. "; 219 LOG(ERROR) << "Lockfile did not parse correctly. ";
243 if (InitializeFiles() < 0 || ParseFiles() < 0) { 220 if (!InitializeFiles() || !ParseFiles()) {
244 LOG(ERROR) << "Failed to create a new lock file!"; 221 LOG(ERROR) << "Failed to create a new lock file!";
245 return -1; 222 return false;
246 } 223 }
247 } 224 }
248 225
249 DCHECK(dumps_); 226 DCHECK(dumps_);
250 DCHECK(metadata_); 227 DCHECK(metadata_);
251 228
252 // We successfully have acquired the lock. 229 // We successfully have acquired the lock.
253 return 0; 230 return true;
254 } 231 }
255 232
256 int SynchronizedMinidumpManager::ParseFiles() { 233 bool SynchronizedMinidumpManager::ParseFiles() {
257 DCHECK_GE(lockfile_fd_, 0); 234 DCHECK_GE(lockfile_fd_, 0);
258 DCHECK(!dumps_); 235 DCHECK(!dumps_);
259 DCHECK(!metadata_); 236 DCHECK(!metadata_);
260 237
261 std::string lockfile; 238 std::string lockfile;
262 RCHECK(ReadFileToString(base::FilePath(lockfile_path_), &lockfile), -1); 239 RCHECK(ReadFileToString(lockfile_path_, &lockfile), false);
263 240
264 std::vector<std::string> lines = base::SplitString( 241 std::vector<std::string> lines = base::SplitString(
265 lockfile, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); 242 lockfile, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
266 243
267 std::unique_ptr<base::ListValue> dumps = 244 std::unique_ptr<base::ListValue> dumps =
268 base::WrapUnique(new base::ListValue()); 245 base::WrapUnique(new base::ListValue());
269 246
270 // Validate dumps 247 // Validate dumps
271 for (const std::string& line : lines) { 248 for (const std::string& line : lines) {
272 if (line.size() == 0) 249 if (line.size() == 0)
273 continue; 250 continue;
274 std::unique_ptr<base::Value> dump_info = DeserializeFromJson(line); 251 std::unique_ptr<base::Value> dump_info = DeserializeFromJson(line);
275 DumpInfo info(dump_info.get()); 252 DumpInfo info(dump_info.get());
276 RCHECK(info.valid(), -1); 253 RCHECK(info.valid(), false);
277 dumps->Append(std::move(dump_info)); 254 dumps->Append(std::move(dump_info));
278 } 255 }
279 256
280 std::unique_ptr<base::Value> metadata = 257 std::unique_ptr<base::Value> metadata =
281 DeserializeJsonFromFile(base::FilePath(metadata_path_)); 258 DeserializeJsonFromFile(metadata_path_);
282 RCHECK(ValidateMetadata(metadata.get()), -1); 259 RCHECK(ValidateMetadata(metadata.get()), false);
283 260
284 dumps_ = std::move(dumps); 261 dumps_ = std::move(dumps);
285 metadata_ = std::move(metadata); 262 metadata_ = std::move(metadata);
286 return 0; 263 return true;
287 } 264 }
288 265
289 int SynchronizedMinidumpManager::WriteFiles(const base::ListValue* dumps, 266 bool SynchronizedMinidumpManager::WriteFiles(const base::ListValue* dumps,
290 const base::Value* metadata) { 267 const base::Value* metadata) {
291 DCHECK(dumps); 268 DCHECK(dumps);
292 DCHECK(metadata); 269 DCHECK(metadata);
293 std::string lockfile; 270 std::string lockfile;
294 271
295 for (const auto& elem : *dumps) { 272 for (const auto& elem : *dumps) {
296 std::unique_ptr<std::string> dump_info = SerializeToJson(*elem); 273 std::unique_ptr<std::string> dump_info = SerializeToJson(*elem);
297 RCHECK(dump_info, -1); 274 RCHECK(dump_info, false);
298 lockfile += *dump_info; 275 lockfile += *dump_info;
299 lockfile += "\n"; // Add line seperatators 276 lockfile += "\n"; // Add line seperatators
300 } 277 }
301 278
302 if (WriteFile(base::FilePath(lockfile_path_), 279 if (WriteFile(lockfile_path_, lockfile.c_str(), lockfile.size()) < 0) {
303 lockfile.c_str(), 280 return false;
304 lockfile.size()) < 0) {
305 return -1;
306 } 281 }
307 282
308 return SerializeJsonToFile(base::FilePath(metadata_path_), *metadata) ? 0 283 return SerializeJsonToFile(metadata_path_, *metadata);
309 : -1;
310 } 284 }
311 285
312 int SynchronizedMinidumpManager::InitializeFiles() { 286 bool SynchronizedMinidumpManager::InitializeFiles() {
313 std::unique_ptr<base::DictionaryValue> metadata = 287 std::unique_ptr<base::DictionaryValue> metadata =
314 base::WrapUnique(new base::DictionaryValue()); 288 base::WrapUnique(new base::DictionaryValue());
315 289
316 base::DictionaryValue* ratelimit_fields = new base::DictionaryValue(); 290 base::DictionaryValue* ratelimit_fields = new base::DictionaryValue();
317 metadata->Set(kLockfileRatelimitKey, base::WrapUnique(ratelimit_fields)); 291 metadata->Set(kLockfileRatelimitKey, base::WrapUnique(ratelimit_fields));
318 ratelimit_fields->SetString(kLockfileRatelimitPeriodStartKey, "0"); 292 ratelimit_fields->SetDouble(kLockfileRatelimitPeriodStartKey, 0.0);
319 ratelimit_fields->SetInteger(kLockfileRatelimitPeriodDumpsKey, 0); 293 ratelimit_fields->SetInteger(kLockfileRatelimitPeriodDumpsKey, 0);
320 294
321 std::unique_ptr<base::ListValue> dumps = 295 std::unique_ptr<base::ListValue> dumps =
322 base::WrapUnique(new base::ListValue()); 296 base::WrapUnique(new base::ListValue());
323 297
324 return WriteFiles(dumps.get(), metadata.get()); 298 return WriteFiles(dumps.get(), metadata.get());
325 } 299 }
326 300
327 int SynchronizedMinidumpManager::AddEntryToLockFile(const DumpInfo& dump_info) { 301 bool SynchronizedMinidumpManager::AddEntryToLockFile(
328 DCHECK_LE(0, lockfile_fd_); 302 const DumpInfo& dump_info) {
303 DCHECK_GE(lockfile_fd_, 0);
329 DCHECK(dumps_); 304 DCHECK(dumps_);
330 305
331 // Make sure dump_info is valid. 306 // Make sure dump_info is valid.
332 if (!dump_info.valid()) { 307 if (!dump_info.valid()) {
333 LOG(ERROR) << "Entry to be added is invalid"; 308 LOG(ERROR) << "Entry to be added is invalid";
334 return -1; 309 return false;
335 } 310 }
336 311
337 dumps_->Append(dump_info.GetAsValue()); 312 dumps_->Append(dump_info.GetAsValue());
338 313 return true;
339 return 0;
340 } 314 }
341 315
342 int SynchronizedMinidumpManager::RemoveEntryFromLockFile(int index) { 316 bool SynchronizedMinidumpManager::RemoveEntryFromLockFile(int index) {
343 return dumps_->Remove(static_cast<size_t>(index), nullptr) ? 0 : -1; 317 return dumps_->Remove(static_cast<uint64_t>(index), nullptr);
344 } 318 }
345 319
346 void SynchronizedMinidumpManager::ReleaseLockFile() { 320 void SynchronizedMinidumpManager::ReleaseLockFile() {
347 // flock is associated with the fd entry in the open fd table, so closing 321 // flock is associated with the fd entry in the open fd table, so closing
348 // all fd's will release the lock. To be safe, we explicitly unlock. 322 // all fd's will release the lock. To be safe, we explicitly unlock.
349 if (lockfile_fd_ >= 0) { 323 if (lockfile_fd_ >= 0) {
350 if (dumps_) 324 if (dumps_)
351 WriteFiles(dumps_.get(), metadata_.get()); 325 WriteFiles(dumps_.get(), metadata_.get());
352 326
353 flock(lockfile_fd_, LOCK_UN); 327 chromecast::UnlockAndCloseFile(lockfile_fd_);
slan 2016/08/08 16:37:10 nit: ns qualifier not needed.
ameyak 2016/08/08 18:00:43 Done.
354 close(lockfile_fd_);
355
356 // We may use this object again, so we should reset this.
357 lockfile_fd_ = -1; 328 lockfile_fd_ = -1;
358 } 329 }
359 330
360 dumps_.reset(); 331 dumps_.reset();
361 metadata_.reset(); 332 metadata_.reset();
362 } 333 }
363 334
364 ScopedVector<DumpInfo> SynchronizedMinidumpManager::GetDumps() { 335 ScopedVector<DumpInfo> SynchronizedMinidumpManager::GetDumps() {
365 ScopedVector<DumpInfo> dumps; 336 ScopedVector<DumpInfo> dumps;
366 337
367 for (const auto& elem : *dumps_) { 338 for (const auto& elem : *dumps_) {
368 dumps.push_back(new DumpInfo(elem.get())); 339 dumps.push_back(new DumpInfo(elem.get()));
369 } 340 }
370 341
371 return dumps; 342 return dumps;
372 } 343 }
373 344
374 int SynchronizedMinidumpManager::SetCurrentDumps( 345 bool SynchronizedMinidumpManager::SetCurrentDumps(
375 const ScopedVector<DumpInfo>& dumps) { 346 const ScopedVector<DumpInfo>& dumps) {
376 dumps_->Clear(); 347 dumps_->Clear();
377 348
378 for (DumpInfo* dump : dumps) 349 for (DumpInfo* dump : dumps)
379 dumps_->Append(dump->GetAsValue()); 350 dumps_->Append(dump->GetAsValue());
380 351
381 return 0; 352 return true;
382 } 353 }
383 354
384 int SynchronizedMinidumpManager::IncrementNumDumpsInCurrentPeriod() { 355 bool SynchronizedMinidumpManager::IncrementNumDumpsInCurrentPeriod() {
385 DCHECK(metadata_); 356 DCHECK(metadata_);
386 int last_dumps = GetRatelimitPeriodDumps(metadata_.get()); 357 int last_dumps = GetRatelimitPeriodDumps(metadata_.get());
387 RCHECK(last_dumps >= 0, -1); 358 RCHECK(last_dumps >= 0, false);
388 359
389 return SetRatelimitPeriodDumps(metadata_.get(), last_dumps + 1); 360 return SetRatelimitPeriodDumps(metadata_.get(), last_dumps + 1);
390 } 361 }
391 362
392 bool SynchronizedMinidumpManager::CanUploadDump() { 363 bool SynchronizedMinidumpManager::CanUploadDump() {
393 time_t cur_time = time(nullptr); 364 base::Time cur_time = base::Time::Now();
394 time_t period_start = GetRatelimitPeriodStart(metadata_.get()); 365 base::Time period_start = GetRatelimitPeriodStart(metadata_.get());
395 int period_dumps_count = GetRatelimitPeriodDumps(metadata_.get()); 366 int period_dumps_count = GetRatelimitPeriodDumps(metadata_.get());
396 367
397 // If we're in invalid state, or we passed the period, reset the ratelimit. 368 // If we're in invalid state, or we passed the period, reset the ratelimit.
398 // When the device reboots, |cur_time| may be incorrectly reported to be a 369 // When the device reboots, |cur_time| may be incorrectly reported to be a
399 // very small number for a short period of time. So only consider 370 // very small number for a short period of time. So only consider
400 // |period_start| invalid when |cur_time| is less if |cur_time| is not very 371 // |period_start| invalid when |cur_time| is less if |cur_time| is not very
401 // close to 0. 372 // close to 0.
402 if (period_dumps_count < 0 || 373 if (period_dumps_count < 0 ||
403 (cur_time < period_start && cur_time > kRatelimitPeriodSeconds) || 374 (cur_time < period_start &&
404 difftime(cur_time, period_start) >= kRatelimitPeriodSeconds) { 375 cur_time.ToDoubleT() > kRatelimitPeriodSeconds) ||
376 (cur_time - period_start).InSeconds() >= kRatelimitPeriodSeconds) {
405 period_start = cur_time; 377 period_start = cur_time;
406 period_dumps_count = 0; 378 period_dumps_count = 0;
407 SetRatelimitPeriodStart(metadata_.get(), period_start); 379 SetRatelimitPeriodStart(metadata_.get(), period_start);
408 SetRatelimitPeriodDumps(metadata_.get(), period_dumps_count); 380 SetRatelimitPeriodDumps(metadata_.get(), period_dumps_count);
409 } 381 }
410 382
411 return period_dumps_count < kRatelimitPeriodMaxDumps; 383 return period_dumps_count < kRatelimitPeriodMaxDumps;
412 } 384 }
413 385
414 bool SynchronizedMinidumpManager::HasDumps() { 386 bool SynchronizedMinidumpManager::HasDumps() {
415 // Check if lockfile has entries. 387 // Check if lockfile has entries.
416 int64_t size = 0; 388 int64_t size = 0;
417 if (GetFileSize(base::FilePath(lockfile_path_), &size) && size > 0) 389 if (base::GetFileSize(lockfile_path_, &size) && size > 0)
418 return true; 390 return true;
419 391
420 // Check if any files are in minidump directory 392 // Check if any files are in minidump directory
421 base::DirReaderPosix reader(dump_path_.value().c_str()); 393 base::DirReaderPosix reader(dump_path_.value().c_str());
422 if (!reader.IsValid()) { 394 if (!reader.IsValid()) {
423 DLOG(FATAL) << "Could not open minidump dir: " << dump_path_.value(); 395 DLOG(FATAL) << "Could not open minidump dir: " << dump_path_.value();
424 return false; 396 return false;
425 } 397 }
426 398
427 while (reader.Next()) { 399 while (reader.Next()) {
428 if (strcmp(reader.name(), ".") == 0 || strcmp(reader.name(), "..") == 0) 400 if (strcmp(reader.name(), ".") == 0 || strcmp(reader.name(), "..") == 0)
429 continue; 401 continue;
430 402
431 const std::string file_path = dump_path_.Append(reader.name()).value(); 403 const base::FilePath file_path = dump_path_.Append(reader.name());
432 if (file_path != lockfile_path_ && file_path != metadata_path_) 404 if (file_path != lockfile_path_ && file_path != metadata_path_)
433 return true; 405 return true;
434 } 406 }
435 407
436 return false; 408 return false;
437 } 409 }
438 410
439 } // namespace chromecast 411 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698