| Index: src/platform/crash/crash_reporter.cc
|
| diff --git a/src/platform/crash/crash_reporter.cc b/src/platform/crash/crash_reporter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..234ab830834fe20a6f73784b8cb5bce5a269bfe6
|
| --- /dev/null
|
| +++ b/src/platform/crash/crash_reporter.cc
|
| @@ -0,0 +1,115 @@
|
| +// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/file_util.h"
|
| +#include "base/logging.h"
|
| +#include "base/string_util.h"
|
| +#include "crash/system_logging.h"
|
| +#include "crash/user_collector.h"
|
| +#include "gflags/gflags.h"
|
| +#include "metrics_library.h"
|
| +
|
| +DEFINE_bool(init, false, "Initialize crash logging");
|
| +DEFINE_bool(clean_shutdown, false, "Signal clean shutdown");
|
| +DEFINE_string(exec, "", "Executable name crashed");
|
| +DEFINE_int32(pid, -1, "Crashing PID");
|
| +DEFINE_int32(signal, -1, "Signal causing crash");
|
| +DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
|
| +
|
| +static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
|
| +static const char kUncleanShutdownFile[] =
|
| + "/var/lib/crash_reporter/pending_clean_shutdown";
|
| +
|
| +// Enumeration of kinds of crashes to be used in the CrashCounter histogram.
|
| +enum CrashKinds {
|
| + CRASH_KIND_KERNEL = 1,
|
| + CRASH_KIND_USER = 2,
|
| + CRASH_KIND_MAX
|
| +};
|
| +
|
| +static SystemLoggingImpl s_system_log;
|
| +
|
| +static bool IsMetricsCollectionAllowed() {
|
| + // TODO(kmixter): Eventually check system tainted state and
|
| + // move this down in metrics library where it would be explicitly
|
| + // checked when asked to send stats.
|
| + return true;
|
| +}
|
| +
|
| +static void CheckUncleanShutdown() {
|
| + FilePath unclean_file_path(kUncleanShutdownFile);
|
| + if (!file_util::PathExists(unclean_file_path)) {
|
| + return;
|
| + }
|
| + s_system_log.LogWarning("Last shutdown was not clean");
|
| + if (IsMetricsCollectionAllowed()) {
|
| + MetricsLibrary::SendEnumToChrome(std::string(kCrashCounterHistogram),
|
| + CRASH_KIND_KERNEL,
|
| + CRASH_KIND_MAX);
|
| + }
|
| + if (!file_util::Delete(unclean_file_path, false)) {
|
| + s_system_log.LogError("Failed to delete unclean shutdown file %s",
|
| + kUncleanShutdownFile);
|
| + }
|
| +}
|
| +
|
| +static bool PrepareUncleanShutdownCheck() {
|
| + static const char empty[] = "";
|
| + FilePath file_path(kUncleanShutdownFile);
|
| + file_util::CreateDirectory(file_path.DirName());
|
| + return file_util::WriteFile(file_path, empty, 0) == 0;
|
| +}
|
| +
|
| +static void SignalCleanShutdown() {
|
| + s_system_log.LogInfo("Clean shutdown signalled");
|
| + file_util::Delete(FilePath(kUncleanShutdownFile), false);
|
| +}
|
| +
|
| +static void CountUserCrash() {
|
| + CHECK(IsMetricsCollectionAllowed());
|
| + MetricsLibrary::SendEnumToChrome(std::string(kCrashCounterHistogram),
|
| + CRASH_KIND_USER,
|
| + CRASH_KIND_MAX);
|
| +}
|
| +
|
| +int main(int argc, char *argv[]) {
|
| + google::ParseCommandLineFlags(&argc, &argv, true);
|
| + FilePath my_path(argv[0]);
|
| + file_util::AbsolutePath(&my_path);
|
| + s_system_log.Initialize(my_path.BaseName().value().c_str());
|
| + UserCollector user_collector;
|
| + user_collector.Initialize(CountUserCrash,
|
| + my_path.value(),
|
| + IsMetricsCollectionAllowed,
|
| + &s_system_log);
|
| +
|
| + if (FLAGS_init) {
|
| + CHECK(!FLAGS_clean_shutdown) << "Incompatible options";
|
| + user_collector.Enable();
|
| + if (FLAGS_unclean_check) {
|
| + CheckUncleanShutdown();
|
| + if (!PrepareUncleanShutdownCheck()) {
|
| + s_system_log.LogError("Unable to create shutdown check file");
|
| + }
|
| + }
|
| + return 0;
|
| + }
|
| +
|
| + if (FLAGS_clean_shutdown) {
|
| + SignalCleanShutdown();
|
| + user_collector.Disable();
|
| + return 0;
|
| + }
|
| +
|
| + // Handle a specific user space crash.
|
| + CHECK(FLAGS_signal != -1) << "Signal must be set";
|
| + CHECK(FLAGS_pid != -1) << "PID must be set";
|
| + CHECK(FLAGS_exec != "") << "Executable name must be set";
|
| +
|
| + user_collector.HandleCrash(FLAGS_signal, FLAGS_pid, FLAGS_exec);
|
| +
|
| + return 0;
|
| +}
|
|
|