| // 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. | |
| #ifndef SRC_DEVELOPER_FORENSICS_EXCEPTIONS_PROCESS_LIMBO_MANAGER_H_ | |
| #define SRC_DEVELOPER_FORENSICS_EXCEPTIONS_PROCESS_LIMBO_MANAGER_H_ | |
| #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 { | |
| public: | |
| static constexpr size_t kMaxFilters = 32; | |
| ProcessLimboManager(); | |
| 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); | |
| } | |
| private: | |
| // 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(fxbug.dev/45962): 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 { | |
| public: | |
| 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 WatchActive(WatchActiveCallback) 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; | |
| private: | |
| // 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 | |
| #endif // SRC_DEVELOPER_FORENSICS_EXCEPTIONS_PROCESS_LIMBO_MANAGER_H_ |