| // 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 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; |
| |
| 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_ |