blob: b74472d7345bbb59bc4fdfe823294cbcb31c3a91 [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.
#ifndef SRC_DEVELOPER_DEBUG_DEBUG_AGENT_LIMBO_PROVIDER_H_
#define SRC_DEVELOPER_DEBUG_DEBUG_AGENT_LIMBO_PROVIDER_H_
#include <fuchsia/exception/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/service_directory.h>
#include <map>
#include <optional>
#include <vector>
#include "src/lib/fxl/memory/weak_ptr.h"
namespace debug_agent {
// In charge of providing access to the ProcessLimbo.
//
// Fuchsia can be configured to keep processes that have excepted in a suspension state, called
// Limbo. This provides the possibility for debuggers to attach to those process way after the
// exception occurred. We call this process Just In Time Debugging (JITD).
class LimboProvider {
public:
using OnEnterLimboCallback =
fit::function<void(std::vector<fuchsia::exception::ProcessExceptionMetadata>)>;
explicit LimboProvider(std::shared_ptr<sys::ServiceDirectory> services);
virtual ~LimboProvider();
// Init must be called after constructing the object.
// It will get the current state of the limbo being connected and then issue async calls to keep
// that state updated. If the provider is valid, |limbo()| is guaranteed to be up to date.
//
// |error_handler| will only be used if |Init| was successful. Once the error handler has been
// issued, this provider is considered invalid and Init should be called again.
virtual zx_status_t Init();
// Callback to be called whenever new processes enter the connected limbo.
// See |on_enter_limbo_| for more details.
void set_on_enter_limbo(OnEnterLimboCallback cb) { on_enter_limbo_ = std::move(cb); }
// Limbo can fail to initialize (eg. failed to connect). There is no point querying an invalid
// limbo provider, so callers should check for validity before using it. If the limbo is invalid,
// callers should either attempt to initialize again or create another limbo provider.
//
// NOTE: a valid limbo provider might be inactive (see ProcessLimbo fidl declaration) and/or be
// empty (not have any processes waiting on an exception).
virtual bool Valid() const;
virtual const std::map<zx_koid_t, fuchsia::exception::ProcessExceptionMetadata>& Limbo() const;
virtual zx_status_t RetrieveException(zx_koid_t process_koid,
fuchsia::exception::ProcessException* out);
virtual zx_status_t ReleaseProcess(zx_koid_t process_koid);
protected:
// Callback to be triggered whenever a new process enters the the limbo. Provides the list of
// new processes that just entered the limbo on this event. |Limbo()| is up to date at the moment
// of this callback.
OnEnterLimboCallback on_enter_limbo_;
private:
void Reset();
void WatchActive();
void WatchLimbo();
bool valid_ = false;
// Because the Process Limbo uses hanging gets (async callbacks) and this class exposes a
// synchronous inteface, we need to keep track of the current state in order to be able to
// return it immediatelly.
std::map<zx_koid_t, fuchsia::exception::ProcessExceptionMetadata> limbo_;
bool is_limbo_active_ = false;
fuchsia::exception::ProcessLimboPtr connection_;
std::shared_ptr<sys::ServiceDirectory> services_;
};
} // namespace debug_agent
#endif // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_LIMBO_PROVIDER_H_