blob: 08a6ff49efafcdd02f94ecd1474e630966bf331c [file] [log] [blame]
// Copyright 2019 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/generic_failure_collector.h"
#include <memory>
#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include "crash-reporter/util.h"
namespace {
const char kSignatureKey[] = "sig";
} // namespace
using base::FilePath;
using base::StringPrintf;
const char* const GenericFailureCollector::kAuthFailure = "auth-failure";
const char* const GenericFailureCollector::kSuspendFailure = "suspend-failure";
const char* const GenericFailureCollector::kServiceFailure = "service-failure";
const char* const GenericFailureCollector::kArcServiceFailure =
"arc-service-failure";
GenericFailureCollector::GenericFailureCollector()
: CrashCollector("generic_failure"), failure_report_path_("/dev/stdin") {}
GenericFailureCollector::~GenericFailureCollector() {}
bool GenericFailureCollector::LoadGenericFailure(std::string* content,
std::string* signature) {
FilePath failure_report_path(failure_report_path_.c_str());
if (!base::ReadFileToString(failure_report_path, content)) {
LOG(ERROR) << "Could not open " << failure_report_path.value();
return false;
}
std::string::size_type end_position = content->find('\n');
if (end_position == std::string::npos) {
LOG(ERROR) << "unexpected generic failure format";
return false;
}
*signature = content->substr(0, end_position);
return true;
}
bool GenericFailureCollector::CollectFull(const std::string& exec_name,
const std::string& log_key_name,
base::Optional<int> weight) {
LOG(INFO) << "Processing generic failure";
std::string generic_failure;
std::string failure_signature;
if (!LoadGenericFailure(&generic_failure, &failure_signature)) {
return true;
}
FilePath crash_directory;
if (!GetCreatedCrashDirectoryByEuid(kRootUid, &crash_directory, nullptr)) {
return true;
}
std::string dump_basename = FormatDumpBasename(exec_name, time(nullptr), 0);
FilePath log_path = GetCrashPath(crash_directory, dump_basename, "log");
FilePath meta_path = GetCrashPath(crash_directory, dump_basename, "meta");
if (weight) {
AddCrashMetaUploadData("weight", StringPrintf("%d", *weight));
}
AddCrashMetaData(kSignatureKey, failure_signature);
bool result = GetLogContents(log_config_path_, log_key_name, log_path);
if (result) {
FinishCrash(meta_path, exec_name, log_path.BaseName().value());
}
return true;
}
// static
CollectorInfo GenericFailureCollector::GetHandlerInfo(
bool suspend_failure,
bool auth_failure,
const std::string& arc_service_failure,
const std::string& service_failure) {
auto generic_failure_collector = std::make_shared<GenericFailureCollector>();
return {
.collector = generic_failure_collector,
.handlers = {{
.should_handle = suspend_failure,
.cb = base::BindRepeating(
&GenericFailureCollector::CollectWithWeight,
generic_failure_collector, kSuspendFailure,
util::GetSuspendFailureWeight()),
},
{
.should_handle = auth_failure,
.cb = base::BindRepeating(
&GenericFailureCollector::Collect,
generic_failure_collector, kAuthFailure),
},
{
.should_handle = !arc_service_failure.empty(),
.cb = base::BindRepeating(
&GenericFailureCollector::CollectFull,
generic_failure_collector,
StringPrintf("%s-%s", kArcServiceFailure,
arc_service_failure.c_str()),
kArcServiceFailure, util::GetServiceFailureWeight()),
},
{
.should_handle = !service_failure.empty(),
.cb = base::BindRepeating(
&GenericFailureCollector::CollectFull,
generic_failure_collector,
StringPrintf("%s-%s", kServiceFailure,
service_failure.c_str()),
kServiceFailure, util::GetServiceFailureWeight()),
}}};
}