mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
handler: Add --monitor-self-annotations
--monitor-self-annotations allows the Crashpad-using application to push module-level annotations in to crashpad_handler. These annotations will appear in any crash report written for that handler by --monitor-self. Bug: crashpad:143 Change-Id: If47395da75a90be4f4bdce0630ce95ea93f9fcf3 Reviewed-on: https://chromium-review.googlesource.com/467746 Reviewed-by: Scott Graham <scottmg@chromium.org>
This commit is contained in:
parent
45305395ad
commit
8f07f7481a
@ -149,15 +149,28 @@ establish the Crashpad client environment before running a program.
|
||||
Causes a second instance of the Crashpad handler program to be started,
|
||||
monitoring the original instance for exceptions. The original instance will
|
||||
become a client of the second one. The second instance will be started with
|
||||
the same **--annotation**, **--database**, **--no-rate-limit**,
|
||||
**--no-upload-gzip**, and **--url** arguments as the original one. The second
|
||||
instance will not be started with a **--metrics-dir** argument even if the
|
||||
original instance was.
|
||||
the same **--annotation**, **--database**, **--monitor-self-annotation**,
|
||||
**--no-rate-limit**, **--no-upload-gzip**, and **--url** arguments as the
|
||||
original one. The second instance will not be started with a
|
||||
**--metrics-dir** argument even if the original instance was.
|
||||
|
||||
Where supported by the underlying operating system, the second instance will
|
||||
be restarted should it exit before the first instance. The second instance
|
||||
will not be eligible to be started asynchronously.
|
||||
|
||||
* **--monitor-self-annotation**=_KEY_=_VALUE_
|
||||
|
||||
Sets a module-level annotation mapping _KEY_ to _VALUE_ in the Crashpad
|
||||
handler. This option may appear zero, one, or more times.
|
||||
|
||||
If **--monitor-self** is in use, the second instance of the Crashpad handler
|
||||
program will find these annotations stored in the original instance and will
|
||||
include them in any crash reports written for the original instance.
|
||||
|
||||
These annotations will only appear in crash reports written for the Crashpad
|
||||
handler itself. To apply a process-level annotation to all crash reports
|
||||
written by an instance of the Crashpad handler, use **--annotation** instead.
|
||||
|
||||
* **--monitor-self-argument**=_ARGUMENT_
|
||||
|
||||
When directed by **--monitor-self** to start a second instance of the
|
||||
|
@ -34,11 +34,14 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/metrics/persistent_histogram_allocator.h"
|
||||
#include "base/scoped_generic.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "client/crash_report_database.h"
|
||||
#include "client/crashpad_client.h"
|
||||
#include "client/crashpad_info.h"
|
||||
#include "client/prune_crash_reports.h"
|
||||
#include "client/simple_string_dictionary.h"
|
||||
#include "handler/crash_report_upload_thread.h"
|
||||
#include "handler/prune_crash_reports_thread.h"
|
||||
#include "tools/tool_support.h"
|
||||
@ -102,6 +105,8 @@ void Usage(const base::FilePath& me) {
|
||||
#endif // OS_MACOSX
|
||||
" --metrics-dir=DIR store metrics files in DIR (only in Chromium)\n"
|
||||
" --monitor-self run a second handler to catch crashes in the first\n"
|
||||
" --monitor-self-annotation=KEY=VALUE\n"
|
||||
" set a module annotation in the handler\n"
|
||||
" --monitor-self-argument=ARGUMENT\n"
|
||||
" provide additional arguments to the second handler\n"
|
||||
" --no-rate-limit don't rate limit crash uploads\n"
|
||||
@ -123,6 +128,7 @@ void Usage(const base::FilePath& me) {
|
||||
|
||||
struct Options {
|
||||
std::map<std::string, std::string> annotations;
|
||||
std::map<std::string, std::string> monitor_self_annotations;
|
||||
std::string url;
|
||||
base::FilePath database;
|
||||
base::FilePath metrics_dir;
|
||||
@ -140,6 +146,29 @@ struct Options {
|
||||
bool upload_gzip;
|
||||
};
|
||||
|
||||
// Splits |key_value| on '=' and inserts the resulting key and value into |map|.
|
||||
// If |key_value| has the wrong format, logs an error and returns false. If the
|
||||
// key is already in the map, logs a warning, replaces the existing value, and
|
||||
// returns true. If the key and value were inserted into the map, returns true.
|
||||
// |argument| is used to give context to logged messages.
|
||||
bool AddKeyValueToMap(std::map<std::string, std::string>* map,
|
||||
const std::string& key_value,
|
||||
const char* argument) {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if (!SplitStringFirst(key_value, '=', &key, &value)) {
|
||||
LOG(ERROR) << argument << " requires KEY=VALUE";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string old_value;
|
||||
if (!MapInsertOrReplace(map, key, value, &old_value)) {
|
||||
LOG(WARNING) << argument << " has duplicate key " << key
|
||||
<< ", discarding value " << old_value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calls Metrics::HandlerLifetimeMilestone, but only on the first call. This is
|
||||
// to prevent multiple exit events from inadvertently being recorded, which
|
||||
// might happen if a crash occurs during destruction in what would otherwise be
|
||||
@ -292,7 +321,7 @@ class TerminateHandler final : public SessionEndWatcher {
|
||||
void ReinstallCrashHandler() {
|
||||
// This is used to re-enable the metrics-recording crash handler after
|
||||
// MonitorSelf() sets up a Crashpad exception handler. The Crashpad handler
|
||||
// takes over the UnhandledExceptionFilter, so reintsall the metrics-recording
|
||||
// takes over the UnhandledExceptionFilter, so reinstall the metrics-recording
|
||||
// one.
|
||||
g_original_exception_filter =
|
||||
SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
|
||||
@ -330,6 +359,12 @@ void MonitorSelf(const Options& options) {
|
||||
if (!options.upload_gzip) {
|
||||
extra_arguments.push_back("--no-upload-gzip");
|
||||
}
|
||||
for (const auto& iterator : options.monitor_self_annotations) {
|
||||
extra_arguments.push_back(
|
||||
base::StringPrintf("--monitor-self-annotation=%s=%s",
|
||||
iterator.first.c_str(),
|
||||
iterator.second.c_str()));
|
||||
}
|
||||
|
||||
// Don’t use options.metrics_dir. The current implementation only allows one
|
||||
// instance of crashpad_handler to be writing metrics at a time, and it should
|
||||
@ -377,6 +412,7 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
#endif // OS_MACOSX
|
||||
kOptionMetrics,
|
||||
kOptionMonitorSelf,
|
||||
kOptionMonitorSelfAnnotation,
|
||||
kOptionMonitorSelfArgument,
|
||||
kOptionNoRateLimit,
|
||||
kOptionNoUploadGzip,
|
||||
@ -410,6 +446,10 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
#endif // OS_MACOSX
|
||||
{"metrics-dir", required_argument, nullptr, kOptionMetrics},
|
||||
{"monitor-self", no_argument, nullptr, kOptionMonitorSelf},
|
||||
{"monitor-self-annotation",
|
||||
required_argument,
|
||||
nullptr,
|
||||
kOptionMonitorSelfAnnotation},
|
||||
{"monitor-self-argument",
|
||||
required_argument,
|
||||
nullptr,
|
||||
@ -442,17 +482,9 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
while ((opt = getopt_long(argc, argv, "", long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case kOptionAnnotation: {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if (!SplitStringFirst(optarg, '=', &key, &value)) {
|
||||
ToolSupport::UsageHint(me, "--annotation requires KEY=VALUE");
|
||||
if (!AddKeyValueToMap(&options.annotations, optarg, "--annotation")) {
|
||||
return ExitFailure();
|
||||
}
|
||||
std::string old_value;
|
||||
if (!MapInsertOrReplace(&options.annotations, key, value, &old_value)) {
|
||||
LOG(WARNING) << "duplicate key " << key << ", discarding value "
|
||||
<< old_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kOptionDatabase: {
|
||||
@ -494,6 +526,14 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
options.monitor_self = true;
|
||||
break;
|
||||
}
|
||||
case kOptionMonitorSelfAnnotation: {
|
||||
if (!AddKeyValueToMap(&options.monitor_self_annotations,
|
||||
optarg,
|
||||
"--monitor-self-annotation")) {
|
||||
return ExitFailure();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kOptionMonitorSelfArgument: {
|
||||
options.monitor_self_arguments.push_back(optarg);
|
||||
break;
|
||||
@ -584,6 +624,17 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
MonitorSelf(options);
|
||||
}
|
||||
|
||||
if (!options.monitor_self_annotations.empty()) {
|
||||
// Establish these annotations even if --monitor-self is not present, in
|
||||
// case something such as generate_dump wants to try to access them later.
|
||||
SimpleStringDictionary* module_annotations = new SimpleStringDictionary();
|
||||
for (const auto& iterator : options.monitor_self_annotations) {
|
||||
module_annotations->SetKeyValue(iterator.first.c_str(),
|
||||
iterator.second.c_str());
|
||||
}
|
||||
CrashpadInfo::GetCrashpadInfo()->set_simple_annotations(module_annotations);
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
if (options.mach_service.empty()) {
|
||||
// Don’t do this when being run by launchd. See launchd.plist(5).
|
||||
|
Loading…
x
Reference in New Issue
Block a user