mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
crashpad_database_util: add --new-report.
R=rsesek@chromium.org Review URL: https://codereview.chromium.org/1018853006
This commit is contained in:
parent
678baca8bd
commit
ab23906193
@ -17,8 +17,31 @@
|
||||
namespace crashpad {
|
||||
|
||||
CrashReportDatabase::Report::Report()
|
||||
: uuid(), file_path(), id(), creation_time(0), uploaded(false),
|
||||
last_upload_attempt_time(0), upload_attempts(0) {
|
||||
: uuid(),
|
||||
file_path(),
|
||||
id(),
|
||||
creation_time(0),
|
||||
uploaded(false),
|
||||
last_upload_attempt_time(0),
|
||||
upload_attempts(0) {
|
||||
}
|
||||
|
||||
CrashReportDatabase::CallErrorWritingCrashReport::CallErrorWritingCrashReport(
|
||||
CrashReportDatabase* database,
|
||||
NewReport* new_report)
|
||||
: database_(database),
|
||||
new_report_(new_report) {
|
||||
}
|
||||
|
||||
CrashReportDatabase::CallErrorWritingCrashReport::
|
||||
~CallErrorWritingCrashReport() {
|
||||
if (new_report_) {
|
||||
database_->ErrorWritingCrashReport(new_report_);
|
||||
}
|
||||
}
|
||||
|
||||
void CrashReportDatabase::CallErrorWritingCrashReport::Disarm() {
|
||||
new_report_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -106,6 +106,32 @@ class CrashReportDatabase {
|
||||
base::FilePath path;
|
||||
};
|
||||
|
||||
//! \brief A scoper to cleanly handle the interface requirement imposed by
|
||||
//! PrepareNewCrashReport().
|
||||
//!
|
||||
//! Calls ErrorWritingCrashReport() upon destruction unless disarmed by
|
||||
//! calling Disarm(). Armed upon construction.
|
||||
class CallErrorWritingCrashReport {
|
||||
public:
|
||||
//! \brief Arms the object to call ErrorWritingCrashReport() on \a database
|
||||
//! with an argument of \a new_report on destruction.
|
||||
CallErrorWritingCrashReport(CrashReportDatabase* database,
|
||||
NewReport* new_report);
|
||||
|
||||
//! \brief Calls ErrorWritingCrashReport() if the object is armed.
|
||||
~CallErrorWritingCrashReport();
|
||||
|
||||
//! \brief Disarms the object so that CallErrorWritingCrashReport() will not
|
||||
//! be called upon destruction.
|
||||
void Disarm();
|
||||
|
||||
private:
|
||||
CrashReportDatabase* database_; // weak
|
||||
NewReport* new_report_; // weak
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CallErrorWritingCrashReport);
|
||||
};
|
||||
|
||||
//! \brief The result code for operations performed on a database.
|
||||
enum OperationStatus {
|
||||
//! \brief No error occurred.
|
||||
@ -156,12 +182,17 @@ class CrashReportDatabase {
|
||||
//! \brief Creates a record of a new crash report.
|
||||
//!
|
||||
//! Callers can then write the crash report using the file handle provided.
|
||||
//! The caller does not own this handle, and it must be explicitly closed with
|
||||
//! The caller does not own the new crash report record or its file handle,
|
||||
//! both of which must be explicitly disposed of by calling
|
||||
//! FinishedWritingCrashReport() or ErrorWritingCrashReport().
|
||||
//!
|
||||
//! \param[out] report A file handle to which the crash report data should be
|
||||
//! written. Only valid if this returns #kNoError. The caller must not
|
||||
//! close this handle.
|
||||
//! To arrange to call ErrorWritingCrashReport() during any early return, use
|
||||
//! CallErrorWritingCrashReport.
|
||||
//!
|
||||
//! \param[out] report A NewReport object containing a file handle to which
|
||||
//! the crash report data should be written. Only valid if this returns
|
||||
//! #kNoError. The caller must not delete the NewReport object or close
|
||||
//! the file handle within.
|
||||
//!
|
||||
//! \return The operation status code.
|
||||
virtual OperationStatus PrepareNewCrashReport(NewReport** report) = 0;
|
||||
@ -171,8 +202,9 @@ class CrashReportDatabase {
|
||||
//! After calling this method, the database is permitted to move and rename
|
||||
//! the file at NewReport::path.
|
||||
//!
|
||||
//! \param[in] report A handle obtained with PrepareNewCrashReport(). The
|
||||
//! handle will be invalidated as part of this call.
|
||||
//! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The
|
||||
//! NewReport object and file handle within will be invalidated as part of
|
||||
//! this call.
|
||||
//! \param[out] uuid The UUID of this crash report.
|
||||
//!
|
||||
//! \return The operation status code.
|
||||
@ -186,8 +218,9 @@ class CrashReportDatabase {
|
||||
//! After calling this method, the database is permitted to remove the file at
|
||||
//! NewReport::path.
|
||||
//!
|
||||
//! \param[in] report A handle obtained with PrepareNewCrashReport(). The
|
||||
//! handle will be invalidated as part of this call.
|
||||
//! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The
|
||||
//! NewReport object and file handle within will be invalidated as part of
|
||||
//! this call.
|
||||
//!
|
||||
//! \return The operation status code.
|
||||
virtual OperationStatus ErrorWritingCrashReport(NewReport* report) = 0;
|
||||
|
@ -37,37 +37,6 @@
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
namespace {
|
||||
|
||||
// Calls CrashReportDatabase::ErrorWritingCrashReport() upon destruction unless
|
||||
// disarmed by calling Disarm(). Armed upon construction.
|
||||
class CallErrorWritingCrashReport {
|
||||
public:
|
||||
CallErrorWritingCrashReport(CrashReportDatabase* database,
|
||||
CrashReportDatabase::NewReport* new_report)
|
||||
: database_(database),
|
||||
new_report_(new_report) {
|
||||
}
|
||||
|
||||
~CallErrorWritingCrashReport() {
|
||||
if (new_report_) {
|
||||
database_->ErrorWritingCrashReport(new_report_);
|
||||
}
|
||||
}
|
||||
|
||||
void Disarm() {
|
||||
new_report_ = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
CrashReportDatabase* database_; // weak
|
||||
CrashReportDatabase::NewReport* new_report_; // weak
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CallErrorWritingCrashReport);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
CrashReportExceptionHandler::CrashReportExceptionHandler(
|
||||
CrashReportDatabase* database,
|
||||
CrashReportUploadThread* upload_thread,
|
||||
@ -177,8 +146,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
|
||||
|
||||
process_snapshot.SetReportID(new_report->uuid);
|
||||
|
||||
CallErrorWritingCrashReport call_error_writing_crash_report(database_,
|
||||
new_report);
|
||||
CrashReportDatabase::CallErrorWritingCrashReport
|
||||
call_error_writing_crash_report(database_, new_report);
|
||||
|
||||
WeakFileHandleFileWriter file_writer(new_report->handle);
|
||||
|
||||
|
@ -49,6 +49,8 @@ parent directory of 'PATH' exists.
|
||||
*--show-client-id*::
|
||||
Show the client ID stored in the database’s settings. The client ID is formatted
|
||||
as a UUID. The client ID is set when the database is created.
|
||||
man_link:crashpad_handler[8] retrieves the client ID and stores it in crash
|
||||
reports as they are written.
|
||||
|
||||
*--show-uploads-enabled*::
|
||||
Show the status of the uploads-enabled bit stored in the database’s settings.
|
||||
@ -86,7 +88,8 @@ be formatted in string representation per RFC 4122 §3. All metadata for each
|
||||
report found via a *--show-report* option will be shown. If 'UUID' is not found,
|
||||
the string +"not found"+ will be printed. If this program is only requested to
|
||||
show a single report and it is not found, it will treat this as a failure for
|
||||
the purposes of determining its exit status.
|
||||
the purposes of determining its exit status. This option may appear multiple
|
||||
times.
|
||||
|
||||
*--set-report-uploads-enabled*='BOOL'::
|
||||
Enable or disable report upload in the database’s settings. 'BOOL' is a string
|
||||
@ -101,6 +104,11 @@ numeric +time_t+ value, or the special string +"never"+.
|
||||
+
|
||||
See also *--show-last-upload-attempt-time*.
|
||||
|
||||
*--new-report*='PATH'::
|
||||
Submit a new report located at 'PATH' to the database. The new report will be in
|
||||
the “pending” state. The UUID assigned to the new report will be printed. This
|
||||
option may appear multiple times.
|
||||
|
||||
*--utc*::
|
||||
When showing times, do so in UTC as opposed to the local time zone. When setting
|
||||
times, interpret ambiguous time strings in UTC as opposed to the local time
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "client/crash_report_database.h"
|
||||
#include "client/settings.h"
|
||||
#include "tools/tool_support.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "util/file/file_reader.h"
|
||||
#include "util/misc/uuid.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -54,6 +56,7 @@ void Usage(const std::string& me) {
|
||||
" --set-uploads-enabled=BOOL enable or disable uploads\n"
|
||||
" --set-last-upload-attempt-time=TIME\n"
|
||||
" set the last-upload-attempt time to TIME\n"
|
||||
" --new-report=PATH submit a new report at PATH\n"
|
||||
" --utc show and set UTC times instead of local\n"
|
||||
" --help display this help and exit\n"
|
||||
" --version output version information and exit\n",
|
||||
@ -63,6 +66,7 @@ void Usage(const std::string& me) {
|
||||
|
||||
struct Options {
|
||||
std::vector<UUID> show_reports;
|
||||
std::vector<base::FilePath> new_report_paths;
|
||||
const char* database;
|
||||
const char* set_last_upload_attempt_time_string;
|
||||
time_t set_last_upload_attempt_time;
|
||||
@ -252,6 +256,7 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
||||
kOptionShowReport,
|
||||
kOptionSetUploadsEnabled,
|
||||
kOptionSetLastUploadAttemptTime,
|
||||
kOptionNewReport,
|
||||
kOptionUTC,
|
||||
|
||||
// Standard options.
|
||||
@ -282,6 +287,7 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
||||
required_argument,
|
||||
nullptr,
|
||||
kOptionSetLastUploadAttemptTime},
|
||||
{"new-report", required_argument, nullptr, kOptionNewReport},
|
||||
{"utc", no_argument, nullptr, kOptionUTC},
|
||||
{"help", no_argument, nullptr, kOptionHelp},
|
||||
{"version", no_argument, nullptr, kOptionVersion},
|
||||
@ -342,6 +348,10 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
||||
options.set_last_upload_attempt_time_string = optarg;
|
||||
break;
|
||||
}
|
||||
case kOptionNewReport: {
|
||||
options.new_report_paths.push_back(base::FilePath(optarg));
|
||||
break;
|
||||
}
|
||||
case kOptionUTC: {
|
||||
options.utc = true;
|
||||
break;
|
||||
@ -381,12 +391,14 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// --new-report is treated as a show operation because it produces output.
|
||||
const size_t show_operations = options.show_client_id +
|
||||
options.show_uploads_enabled +
|
||||
options.show_last_upload_attempt_time +
|
||||
options.show_pending_reports +
|
||||
options.show_completed_reports +
|
||||
options.show_reports.size();
|
||||
options.show_reports.size() +
|
||||
options.new_report_paths.size();
|
||||
const size_t set_operations =
|
||||
options.has_set_uploads_enabled +
|
||||
(options.set_last_upload_attempt_time_string != nullptr);
|
||||
@ -505,6 +517,45 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (const base::FilePath new_report_path : options.new_report_paths) {
|
||||
FileReader file_reader;
|
||||
if (!file_reader.Open(new_report_path)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
CrashReportDatabase::NewReport* new_report;
|
||||
CrashReportDatabase::OperationStatus status =
|
||||
database->PrepareNewCrashReport(&new_report);
|
||||
if (status != CrashReportDatabase::kNoError) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
CrashReportDatabase::CallErrorWritingCrashReport
|
||||
call_error_writing_crash_report(database.get(), new_report);
|
||||
|
||||
char buf[4096];
|
||||
ssize_t read_result;
|
||||
while ((read_result = file_reader.Read(buf, sizeof(buf))) > 0) {
|
||||
if (!LoggingWriteFile(new_report->handle, buf, read_result)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (read_result < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
call_error_writing_crash_report.Disarm();
|
||||
|
||||
UUID uuid;
|
||||
status = database->FinishedWritingCrashReport(new_report, &uuid);
|
||||
if (status != CrashReportDatabase::kNoError) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char* prefix = (show_operations > 1) ? "New report ID: " : "";
|
||||
printf("%s%s\n", prefix, uuid.ToString().c_str());
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user