Initial commit of crash reporter repo
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
new file mode 100644
index 0000000..951d3fa
--- /dev/null
+++ b/crash_reporter/crash_reporter.cc
@@ -0,0 +1,127 @@
+// 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/metrics_library.h"
+
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+DEFINE_bool(init, false, "Initialize crash logging");
+DEFINE_bool(clean_shutdown, false, "Signal clean shutdown");
+DEFINE_bool(crash_test, false, "Crash test");
+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");
+#pragma GCC diagnostic error "-Wstrict-aliasing"
+
+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 MetricsLibrary s_metrics_lib;
+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()) {
+ s_metrics_lib.SendEnumToUMA(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());
+ s_metrics_lib.SendEnumToUMA(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_metrics_lib.Init();
+ 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";
+
+ // Make it possible to test what happens when we crash while
+ // handling a crash.
+ if (FLAGS_crash_test) {
+ *(char *)0 = 0;
+ return 0;
+ }
+
+ user_collector.HandleCrash(FLAGS_signal, FLAGS_pid, FLAGS_exec);
+
+ return 0;
+}