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