| Index: kernel_collector.cc
|
| diff --git a/kernel_collector.cc b/kernel_collector.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1a79c9d86758275303623d4ee6b4cf153413d593
|
| --- /dev/null
|
| +++ b/kernel_collector.cc
|
| @@ -0,0 +1,118 @@
|
| +// 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 "crash-reporter/kernel_collector.h"
|
| +
|
| +#include "base/file_util.h"
|
| +#include "base/logging.h"
|
| +#include "base/string_util.h"
|
| +#include "crash-reporter/system_logging.h"
|
| +
|
| +static const char kKernelExecName[] = "kernel";
|
| +static const char kPreservedDumpPath[] = "/sys/kernel/debug/preserved/kcrash";
|
| +const pid_t kKernelPid = 0;
|
| +const uid_t kRootUid = 0;
|
| +
|
| +const char KernelCollector::kClearingSequence[] = " ";
|
| +
|
| +KernelCollector::KernelCollector()
|
| + : is_enabled_(false),
|
| + preserved_dump_path_(kPreservedDumpPath) {
|
| +}
|
| +
|
| +KernelCollector::~KernelCollector() {
|
| +}
|
| +
|
| +void KernelCollector::OverridePreservedDumpPath(const FilePath &file_path) {
|
| + preserved_dump_path_ = file_path;
|
| +}
|
| +
|
| +bool KernelCollector::LoadPreservedDump(std::string *contents) {
|
| + // clear contents since ReadFileToString actually appends to the string.
|
| + contents->clear();
|
| + if (!file_util::ReadFileToString(preserved_dump_path_, contents)) {
|
| + logger_->LogError("Unable to read %s",
|
| + preserved_dump_path_.value().c_str());
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool KernelCollector::Enable() {
|
| + if (!file_util::PathExists(preserved_dump_path_)) {
|
| + logger_->LogWarning("Kernel does not support crash dumping");
|
| + return false;
|
| + }
|
| +
|
| + // To enable crashes, we will eventually need to set
|
| + // the chnv bit in BIOS, but it does not yet work.
|
| + logger_->LogInfo("Enabling kernel crash handling");
|
| + is_enabled_ = true;
|
| + return true;
|
| +}
|
| +
|
| +bool KernelCollector::ClearPreservedDump() {
|
| + // It is necessary to write at least one byte to the kcrash file for
|
| + // the log to actually be cleared.
|
| + if (file_util::WriteFile(
|
| + preserved_dump_path_,
|
| + kClearingSequence,
|
| + strlen(kClearingSequence)) != strlen(kClearingSequence)) {
|
| + logger_->LogError("Failed to clear kernel crash dump");
|
| + return false;
|
| + }
|
| + logger_->LogInfo("Cleared kernel crash diagnostics");
|
| + return true;
|
| +}
|
| +
|
| +FilePath KernelCollector::GetKernelCrashPath(
|
| + const FilePath &root_crash_path,
|
| + time_t timestamp) {
|
| + std::string dump_basename =
|
| + FormatDumpBasename(kKernelExecName,
|
| + timestamp,
|
| + kKernelPid);
|
| + return root_crash_path.Append(
|
| + StringPrintf("%s.kcrash", dump_basename.c_str()));
|
| +}
|
| +
|
| +bool KernelCollector::Collect() {
|
| + std::string kernel_dump;
|
| + FilePath root_crash_directory;
|
| + if (!LoadPreservedDump(&kernel_dump)) {
|
| + return false;
|
| + }
|
| + if (kernel_dump.empty()) {
|
| + return false;
|
| + }
|
| + if (is_feedback_allowed_function_()) {
|
| + count_crash_function_();
|
| +
|
| + if (!GetCreatedCrashDirectoryByEuid(kRootUid,
|
| + &root_crash_directory)) {
|
| + return true;
|
| + }
|
| +
|
| + FilePath kernel_crash_path = GetKernelCrashPath(root_crash_directory,
|
| + time(NULL));
|
| + if (file_util::WriteFile(kernel_crash_path,
|
| + kernel_dump.data(),
|
| + kernel_dump.length()) !=
|
| + static_cast<int>(kernel_dump.length())) {
|
| + logger_->LogInfo("Failed to write kernel dump to %s",
|
| + kernel_crash_path.value().c_str());
|
| + return true;
|
| + }
|
| +
|
| + logger_->LogInfo("Collected kernel crash diagnostics into %s",
|
| + kernel_crash_path.value().c_str());
|
| + } else {
|
| + logger_->LogInfo("Crash not saved since metrics disabled");
|
| + }
|
| + if (!ClearPreservedDump()) {
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
|
|