blob: 4ebb21dae6e07abc6c353048b5a1e5fb83ddbab1 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "src/developer/forensics/exceptions/exception_broker.h"
#include <fuchsia/exception/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <string>
#include "src/developer/forensics/exceptions/json_utils.h"
#include "src/lib/files/file.h"
namespace forensics {
namespace exceptions {
namespace {
using fuchsia::exception::ExceptionInfo;
using fuchsia::exception::ProcessException;
constexpr char kEnableJitdConfigPath[] = "/config/data/exceptions/enable_jitd_on_startup.json";
} // namespace
std::unique_ptr<ExceptionBroker> ExceptionBroker::Create(async_dispatcher_t* dispatcher,
inspect::Node* inspect_root,
size_t max_num_handlers,
zx::duration exception_ttl,
const char* override_filepath) {
auto broker = std::unique_ptr<ExceptionBroker>(
new ExceptionBroker(dispatcher, inspect_root, max_num_handlers, exception_ttl));
// Check if JITD should be enabled at startup. For now existence means it's activated.
if (!override_filepath)
override_filepath = kEnableJitdConfigPath;
if (files::IsFile(override_filepath)) {
broker->limbo_manager().SetActive(true);
std::string file_content;
if (!files::ReadFileToString(override_filepath, &file_content)) {
FX_LOGS(WARNING) << "Could not read the config file.";
} else {
broker->limbo_manager().set_filters(ExtractFilters(file_content));
}
}
return broker;
}
ExceptionBroker::ExceptionBroker(async_dispatcher_t* dispatcher, inspect::Node* inspect_root,
size_t max_num_handlers, zx::duration exception_ttl)
: handler_manager_(dispatcher, CrashCounter(inspect_root), max_num_handlers, exception_ttl) {}
// OnException -------------------------------------------------------------------------------------
void ExceptionBroker::OnException(zx::exception exception, ExceptionInfo info,
OnExceptionCallback cb) {
FX_LOGS(INFO) << "Received exception -- pid: " << info.process_koid
<< " tid: " << info.thread_koid;
if (!limbo_manager_.active()) {
handler_manager_.Handle(std::move(exception));
} else {
AddToLimbo(std::move(exception), std::move(info));
}
cb();
}
void ExceptionBroker::IsActive(IsActiveCallback cb) { cb(); }
void ExceptionBroker::AddToLimbo(zx::exception exception, ExceptionInfo info) {
ProcessException process_exception = {};
process_exception.set_exception(std::move(exception));
process_exception.set_info(std::move(info));
zx_status_t status;
zx::process process;
status = process_exception.exception().get_process(&process);
if (status != ZX_OK) {
FX_PLOGS(WARNING, status) << "Could not obtain process handle for exception.";
} else {
process_exception.set_process(std::move(process));
}
zx::thread thread;
status = process_exception.exception().get_thread(&thread);
if (status != ZX_OK) {
FX_PLOGS(WARNING, status) << "Could not obtain thread handle for exception.";
} else {
process_exception.set_thread(std::move(thread));
}
limbo_manager_.AddToLimbo(std::move(process_exception));
}
} // namespace exceptions
} // namespace forensics