blob: 258dd7ed42537cb66328cd61af199b9fae192509 [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 <fuchsia/exception/cpp/fidl.h>
#include <map>
#include <set>
#include "src/lib/fxl/memory/weak_ptr.h"
namespace forensics {
namespace exceptions {
class ProcessLimboHandler;
class ProcessLimboManager {
static constexpr size_t kMaxFilters = 32;
fxl::WeakPtr<ProcessLimboManager> GetWeakPtr();
void AddToLimbo(fuchsia::exception::ProcessException);
// Notify all handlers that limbo changed.
void NotifyLimboChanged();
void AddHandler(fxl::WeakPtr<ProcessLimboHandler> handler);
// Returns true if there was a change of state.
bool SetActive(bool active);
bool active() const { return active_; }
const std::map<zx_koid_t, fuchsia::exception::ProcessException>& limbo() const { return limbo_; }
void set_filters(std::set<std::string> filters) { filters_ = std::move(filters); }
const std::set<std::string>& filters() const { return filters_; }
// Testing utilities.
void AppendFiltersForTesting(const std::vector<std::string>&);
void set_obtain_process_name_fn(fit::function<std::string(zx_handle_t)> fn) {
obtain_process_name_fn_ = std::move(fn);
// Returns the list of process metadata for processes waiting on exceptions
// Corresponds to the return value of |WatchProcessesWaitingOnException|.
std::vector<fuchsia::exception::ProcessExceptionMetadata> ListProcessesInLimbo();
// TODO( This is an extremely naive approach. There are several policies to make
// this more robust:
// - Put a ceiling on the amount of exceptions to be held.
// - Define an eviction policy (FIFO probably).
// - Set a timeout for exceptions (configurable).
// - Decide on a throttle mechanism (if the same process is crashing continously).
std::map<zx_koid_t, fuchsia::exception::ProcessException> limbo_;
bool active_ = false;
std::vector<fxl::WeakPtr<ProcessLimboHandler>> handlers_;
std::set<std::string> filters_;
// Testing won't have valid handles (mocking them is very involved), so we use this function to
// inject the way the manager will get the process name, permitting to test the filtering.
fit::function<std::string(zx_handle_t)> obtain_process_name_fn_;
fxl::WeakPtrFactory<ProcessLimboManager> weak_factory_;
friend class ProcessLimboHandler;
// Handles *one* process limbo connection. Having one handler per connection lets us do patterns
// like hanging get, which requires to recongnize per-connection state. The limbo manager is the
// common state all connections query.
class ProcessLimboHandler : public fuchsia::exception::ProcessLimbo {
explicit ProcessLimboHandler(fxl::WeakPtr<ProcessLimboManager> limbo_manager);
fxl::WeakPtr<ProcessLimboHandler> GetWeakPtr();
void ActiveStateChanged(bool state);
// Called when a process goes in or out of limbo (ProcessLimboManager::AddToLimbo).
void LimboChanged(std::vector<fuchsia::exception::ProcessExceptionMetadata> processes);
// fuchsia.exception.ProcessLimbo implementation.
void SetActive(bool active, SetActiveCallback) override;
void GetActive(GetActiveCallback) override;
void WatchActive(WatchActiveCallback) override;
void ListProcessesWaitingOnException(ListProcessesWaitingOnExceptionCallback) override;
void WatchProcessesWaitingOnException(WatchProcessesWaitingOnExceptionCallback) override;
void RetrieveException(zx_koid_t process_koid, RetrieveExceptionCallback) override;
void ReleaseProcess(zx_koid_t process_koid, ReleaseProcessCallback) override;
void GetFilters(GetFiltersCallback) override;
void AppendFilters(std::vector<std::string> filters, AppendFiltersCallback) override;
void RemoveFilters(std::vector<std::string> filters, RemoveFiltersCallback) override;
// WatchActive hanging get.
bool watch_active_dirty_bit_ = true;
WatchActiveCallback is_active_callback_;
bool watch_limbo_dirty_bit_ = true;
WatchProcessesWaitingOnExceptionCallback watch_limbo_callback_;
fxl::WeakPtr<ProcessLimboManager> limbo_manager_;
fxl::WeakPtrFactory<ProcessLimboHandler> weak_factory_;
} // namespace exceptions
} // namespace forensics