| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/browser_watcher/postmortem_report_collector.h" | 5 #include "components/browser_watcher/postmortem_report_collector.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/debug/activity_analyzer.h" | 9 #include "base/debug/activity_analyzer.h" |
| 10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 const base::FilePath::StringType& debug_file_pattern, | 163 const base::FilePath::StringType& debug_file_pattern, |
| 164 const std::set<base::FilePath>& excluded_debug_files, | 164 const std::set<base::FilePath>& excluded_debug_files, |
| 165 crashpad::CrashReportDatabase* report_database) { | 165 crashpad::CrashReportDatabase* report_database) { |
| 166 DCHECK_NE(true, debug_info_dir.empty()); | 166 DCHECK_NE(true, debug_info_dir.empty()); |
| 167 DCHECK_NE(true, debug_file_pattern.empty()); | 167 DCHECK_NE(true, debug_file_pattern.empty()); |
| 168 DCHECK_NE(nullptr, report_database); | 168 DCHECK_NE(nullptr, report_database); |
| 169 | 169 |
| 170 // Collect the list of files to harvest. | 170 // Collect the list of files to harvest. |
| 171 std::vector<FilePath> debug_files = GetDebugStateFilePaths( | 171 std::vector<FilePath> debug_files = GetDebugStateFilePaths( |
| 172 debug_info_dir, debug_file_pattern, excluded_debug_files); | 172 debug_info_dir, debug_file_pattern, excluded_debug_files); |
| 173 UMA_HISTOGRAM_COUNTS_100("ActivityTracker.Collect.StabilityFileCount", |
| 174 debug_files.size()); |
| 173 | 175 |
| 174 // Determine the crashpad client id. | 176 // Determine the crashpad client id. |
| 175 crashpad::UUID client_id; | 177 crashpad::UUID client_id; |
| 176 crashpad::Settings* settings = report_database->GetSettings(); | 178 crashpad::Settings* settings = report_database->GetSettings(); |
| 177 if (settings) { | 179 if (settings) { |
| 178 // If GetSettings() or GetClientID() fails client_id will be left at its | 180 // If GetSettings() or GetClientID() fails client_id will be left at its |
| 179 // default value, all zeroes, which is appropriate. | 181 // default value, all zeroes, which is appropriate. |
| 180 settings->GetClientID(&client_id); | 182 settings->GetClientID(&client_id); |
| 181 } | 183 } |
| 182 | 184 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 // reports and the crashpad reports they get wrapped into. | 227 // reports and the crashpad reports they get wrapped into. |
| 226 | 228 |
| 227 // Collect the data from the debug file to a proto. Note: a non-empty report | 229 // Collect the data from the debug file to a proto. Note: a non-empty report |
| 228 // is interpreted here as an unclean exit. | 230 // is interpreted here as an unclean exit. |
| 229 std::unique_ptr<StabilityReport> report_proto; | 231 std::unique_ptr<StabilityReport> report_proto; |
| 230 CollectionStatus status = Collect(file, &report_proto); | 232 CollectionStatus status = Collect(file, &report_proto); |
| 231 if (status != SUCCESS) { | 233 if (status != SUCCESS) { |
| 232 // The file was empty, or there was an error collecting the data. Detailed | 234 // The file was empty, or there was an error collecting the data. Detailed |
| 233 // logging happens within the Collect function. | 235 // logging happens within the Collect function. |
| 234 if (!base::DeleteFile(file, false)) | 236 if (!base::DeleteFile(file, false)) |
| 235 LOG(ERROR) << "Failed to delete " << file.value(); | 237 DLOG(ERROR) << "Failed to delete " << file.value(); |
| 236 return status; | 238 return status; |
| 237 } | 239 } |
| 238 DCHECK_NE(nullptr, report_proto.get()); | 240 DCHECK_NE(nullptr, report_proto.get()); |
| 239 | 241 |
| 240 // Prepare a crashpad report. | 242 // Prepare a crashpad report. |
| 241 CrashReportDatabase::NewReport* new_report = nullptr; | 243 CrashReportDatabase::NewReport* new_report = nullptr; |
| 242 CrashReportDatabase::OperationStatus database_status = | 244 CrashReportDatabase::OperationStatus database_status = |
| 243 report_database->PrepareNewCrashReport(&new_report); | 245 report_database->PrepareNewCrashReport(&new_report); |
| 244 if (database_status != CrashReportDatabase::kNoError) { | 246 if (database_status != CrashReportDatabase::kNoError) { |
| 245 LOG(ERROR) << "PrepareNewCrashReport failed"; | 247 // Assume this is recoverable: not deleting the file. |
| 248 DLOG(ERROR) << "PrepareNewCrashReport failed"; |
| 246 return PREPARE_NEW_CRASH_REPORT_FAILED; | 249 return PREPARE_NEW_CRASH_REPORT_FAILED; |
| 247 } | 250 } |
| 248 CrashReportDatabase::CallErrorWritingCrashReport | 251 CrashReportDatabase::CallErrorWritingCrashReport |
| 249 call_error_writing_crash_report(report_database, new_report); | 252 call_error_writing_crash_report(report_database, new_report); |
| 250 | 253 |
| 251 // Write the report to a minidump. | 254 // Write the report to a minidump. |
| 252 if (!WriteReportToMinidump(report_proto.get(), client_id, new_report->uuid, | 255 if (!WriteReportToMinidump(report_proto.get(), client_id, new_report->uuid, |
| 253 reinterpret_cast<FILE*>(new_report->handle))) { | 256 reinterpret_cast<FILE*>(new_report->handle))) { |
| 257 // Assume this is not recoverable and delete the file. |
| 258 if (!base::DeleteFile(file, false)) |
| 259 DLOG(ERROR) << "Failed to delete " << file.value(); |
| 254 return WRITE_TO_MINIDUMP_FAILED; | 260 return WRITE_TO_MINIDUMP_FAILED; |
| 255 } | 261 } |
| 256 | 262 |
| 257 // If the file cannot be deleted, do not report its contents. Note this can | 263 // If the file cannot be deleted, do not report its contents. Note this can |
| 258 // lead to under reporting and retries. However, under reporting is | 264 // lead to under reporting and retries. However, under reporting is |
| 259 // preferable to the over reporting that would happen with a file that | 265 // preferable to the over reporting that would happen with a file that |
| 260 // cannot be deleted. | 266 // cannot be deleted. |
| 261 // TODO(manzagop): metrics for the number of non-deletable files. | 267 // TODO(manzagop): metrics for the number of non-deletable files. |
| 262 if (!base::DeleteFile(file, false)) { | 268 if (!base::DeleteFile(file, false)) { |
| 263 LOG(ERROR) << "Failed to delete " << file.value(); | 269 DLOG(ERROR) << "Failed to delete " << file.value(); |
| 264 return DEBUG_FILE_DELETION_FAILED; | 270 return DEBUG_FILE_DELETION_FAILED; |
| 265 } | 271 } |
| 266 | 272 |
| 267 // Finalize the report wrt the report database. Note that this doesn't trigger | 273 // Finalize the report wrt the report database. Note that this doesn't trigger |
| 268 // an immediate upload, but Crashpad will eventually upload the report (as of | 274 // an immediate upload, but Crashpad will eventually upload the report (as of |
| 269 // writing, the delay is on the order of up to 15 minutes). | 275 // writing, the delay is on the order of up to 15 minutes). |
| 270 call_error_writing_crash_report.Disarm(); | 276 call_error_writing_crash_report.Disarm(); |
| 271 crashpad::UUID unused_report_id; | 277 crashpad::UUID unused_report_id; |
| 272 database_status = report_database->FinishedWritingCrashReport( | 278 database_status = report_database->FinishedWritingCrashReport( |
| 273 new_report, &unused_report_id); | 279 new_report, &unused_report_id); |
| 274 if (database_status != CrashReportDatabase::kNoError) { | 280 if (database_status != CrashReportDatabase::kNoError) { |
| 275 LOG(ERROR) << "FinishedWritingCrashReport failed"; | 281 DLOG(ERROR) << "FinishedWritingCrashReport failed"; |
| 276 return FINISHED_WRITING_CRASH_REPORT_FAILED; | 282 return FINISHED_WRITING_CRASH_REPORT_FAILED; |
| 277 } | 283 } |
| 278 | 284 |
| 279 return SUCCESS; | 285 return SUCCESS; |
| 280 } | 286 } |
| 281 | 287 |
| 282 PostmortemReportCollector::CollectionStatus PostmortemReportCollector::Collect( | 288 PostmortemReportCollector::CollectionStatus PostmortemReportCollector::Collect( |
| 283 const base::FilePath& debug_state_file, | 289 const base::FilePath& debug_state_file, |
| 284 std::unique_ptr<StabilityReport>* report) { | 290 std::unique_ptr<StabilityReport>* report) { |
| 285 DCHECK_NE(nullptr, report); | 291 DCHECK_NE(nullptr, report); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 StabilityReport* report, | 410 StabilityReport* report, |
| 405 const crashpad::UUID& client_id, | 411 const crashpad::UUID& client_id, |
| 406 const crashpad::UUID& report_id, | 412 const crashpad::UUID& report_id, |
| 407 base::PlatformFile minidump_file) { | 413 base::PlatformFile minidump_file) { |
| 408 DCHECK(report); | 414 DCHECK(report); |
| 409 | 415 |
| 410 return WritePostmortemDump(minidump_file, client_id, report_id, report); | 416 return WritePostmortemDump(minidump_file, client_id, report_id, report); |
| 411 } | 417 } |
| 412 | 418 |
| 413 } // namespace browser_watcher | 419 } // namespace browser_watcher |
| OLD | NEW |