| Index: crash_reporter.cc
|
| diff --git a/crash_reporter.cc b/crash_reporter.cc
|
| index 0930cea447e19927f893193b6a02db7eaa7cfaaf..e850e3070800555db1818cec65a20b04a30e4244 100644
|
| --- a/crash_reporter.cc
|
| +++ b/crash_reporter.cc
|
| @@ -7,7 +7,9 @@
|
| #include "base/file_util.h"
|
| #include "base/logging.h"
|
| #include "base/string_util.h"
|
| +#include "crash-reporter/kernel_collector.h"
|
| #include "crash-reporter/system_logging.h"
|
| +#include "crash-reporter/unclean_shutdown_collector.h"
|
| #include "crash-reporter/user_collector.h"
|
| #include "gflags/gflags.h"
|
| #include "metrics/metrics_library.h"
|
| @@ -22,69 +24,52 @@ DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
|
| #pragma GCC diagnostic error "-Wstrict-aliasing"
|
|
|
| static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
|
| -static const char kEmpty[] = "";
|
| +static const char kUserCrashSignal[] =
|
| + "org.chromium.CrashReporter.UserCrash";
|
| 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 {
|
| - kCrashKindKernel = 1,
|
| - kCrashKindUser = 2,
|
| + kCrashKindUncleanShutdown = 1,
|
| + kCrashKindUser = 2,
|
| + kCrashKindKernel = 3,
|
| kCrashKindMax
|
| };
|
|
|
| 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.
|
| +static bool IsFeedbackAllowed() {
|
| + // Once crosbug.com/5814 is fixed, call the is opted in function
|
| + // here.
|
| 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),
|
| - kCrashKindKernel,
|
| - kCrashKindMax);
|
| - }
|
| - if (!file_util::Delete(unclean_file_path, false)) {
|
| - s_system_log.LogError("Failed to delete unclean shutdown file %s",
|
| - kUncleanShutdownFile);
|
| - }
|
| -
|
| - // Touch a file to notify the metrics daemon that a kernel crash has
|
| - // been detected so that it can log the time since the last kernel
|
| - // crash.
|
| - static const char kKernelCrashDetectedFile[] = "/tmp/kernel-crash-detected";
|
| - FilePath crash_detected(kKernelCrashDetectedFile);
|
| - file_util::WriteFile(crash_detected, kEmpty, 0);
|
| +static bool TouchFile(const FilePath &file_path) {
|
| + return file_util::WriteFile(file_path, "", 0) == 0;
|
| }
|
|
|
| -static bool PrepareUncleanShutdownCheck() {
|
| - FilePath file_path(kUncleanShutdownFile);
|
| - file_util::CreateDirectory(file_path.DirName());
|
| - return file_util::WriteFile(file_path, kEmpty, 0) == 0;
|
| +static void CountKernelCrash() {
|
| + s_metrics_lib.SendEnumToUMA(std::string(kCrashCounterHistogram),
|
| + kCrashKindKernel,
|
| + kCrashKindMax);
|
| }
|
|
|
| -static void SignalCleanShutdown() {
|
| - s_system_log.LogInfo("Clean shutdown signalled");
|
| - file_util::Delete(FilePath(kUncleanShutdownFile), false);
|
| +static void CountUncleanShutdown() {
|
| + s_metrics_lib.SendEnumToUMA(std::string(kCrashCounterHistogram),
|
| + kCrashKindUncleanShutdown,
|
| + kCrashKindMax);
|
| }
|
|
|
| static void CountUserCrash() {
|
| - CHECK(IsMetricsCollectionAllowed());
|
| s_metrics_lib.SendEnumToUMA(std::string(kCrashCounterHistogram),
|
| kCrashKindUser,
|
| kCrashKindMax);
|
| -
|
| + std::string command = StringPrintf(
|
| + "/usr/bin/dbus-send --type=signal --system / \"%s\"",
|
| + kUserCrashSignal);
|
| // Announce through D-Bus whenever a user crash happens. This is
|
| // used by the metrics daemon to log active use time between
|
| // crashes.
|
| @@ -93,42 +78,47 @@ static void CountUserCrash() {
|
| // using a dbus library directly. However, this should run
|
| // relatively rarely and longer term we may need to implement a
|
| // better way to do this that doesn't rely on D-Bus.
|
| - int status __attribute__((unused)) =
|
| - system("/usr/bin/dbus-send --type=signal --system / "
|
| - "org.chromium.CrashReporter.UserCrash");
|
| +
|
| + int status __attribute__((unused)) = system(command.c_str());
|
| }
|
|
|
| -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,
|
| - true); // generate_diagnostics
|
| +static int Initialize(KernelCollector *kernel_collector,
|
| + UserCollector *user_collector,
|
| + UncleanShutdownCollector *unclean_shutdown_collector) {
|
| + CHECK(!FLAGS_clean_shutdown) << "Incompatible options";
|
|
|
| - 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;
|
| + bool was_kernel_crash = false;
|
| + bool was_unclean_shutdown = false;
|
| + if (kernel_collector->IsEnabled()) {
|
| + was_kernel_crash = kernel_collector->Collect();
|
| }
|
|
|
| - if (FLAGS_clean_shutdown) {
|
| - SignalCleanShutdown();
|
| - user_collector.Disable();
|
| - return 0;
|
| + if (FLAGS_unclean_check) {
|
| + was_unclean_shutdown = unclean_shutdown_collector->Collect();
|
| + }
|
| +
|
| + // Touch a file to notify the metrics daemon that a kernel
|
| + // crash has been detected so that it can log the time since
|
| + // the last kernel crash.
|
| + if (IsFeedbackAllowed()) {
|
| + if (was_kernel_crash) {
|
| + TouchFile(FilePath("/tmp/kernel-crash-detected"));
|
| + } else if (was_unclean_shutdown) {
|
| + // We only count an unclean shutdown if it did not come with
|
| + // an associated kernel crash.
|
| + TouchFile(FilePath("/tmp/unclean-shutdown-detected"));
|
| + }
|
| }
|
|
|
| + // Must enable the unclean shutdown collector *after* collecting.
|
| + kernel_collector->Enable();
|
| + unclean_shutdown_collector->Enable();
|
| + user_collector->Enable();
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +static int HandleUserCrash(UserCollector *user_collector) {
|
| // Handle a specific user space crash.
|
| CHECK(FLAGS_signal != -1) << "Signal must be set";
|
| CHECK(FLAGS_pid != -1) << "PID must be set";
|
| @@ -141,9 +131,45 @@ int main(int argc, char *argv[]) {
|
| }
|
|
|
| // Handle the crash, get the name of the process from procfs.
|
| - if (!user_collector.HandleCrash(FLAGS_signal, FLAGS_pid, NULL)) {
|
| + if (!user_collector->HandleCrash(FLAGS_signal, FLAGS_pid, NULL)) {
|
| return 1;
|
| }
|
| -
|
| return 0;
|
| }
|
| +
|
| +
|
| +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());
|
| + KernelCollector kernel_collector;
|
| + kernel_collector.Initialize(CountKernelCrash,
|
| + IsFeedbackAllowed,
|
| + &s_system_log);
|
| + UserCollector user_collector;
|
| + user_collector.Initialize(CountUserCrash,
|
| + my_path.value(),
|
| + IsFeedbackAllowed,
|
| + &s_system_log,
|
| + true); // generate_diagnostics
|
| + UncleanShutdownCollector unclean_shutdown_collector;
|
| + unclean_shutdown_collector.Initialize(CountUncleanShutdown,
|
| + IsFeedbackAllowed,
|
| + &s_system_log);
|
| +
|
| + if (FLAGS_init) {
|
| + return Initialize(&kernel_collector,
|
| + &user_collector,
|
| + &unclean_shutdown_collector);
|
| + }
|
| +
|
| + if (FLAGS_clean_shutdown) {
|
| + unclean_shutdown_collector.Disable();
|
| + user_collector.Disable();
|
| + return 0;
|
| + }
|
| +
|
| + return HandleUserCrash(&user_collector);
|
| +}
|
|
|