blob: 202969caca6c3cddf34d784cd141d2f68029856d [file] [log] [blame]
// Copyright 2022 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_SYS_FUZZING_COMMON_ASYNC_EVENTPAIR_H_
#define SRC_SYS_FUZZING_COMMON_ASYNC_EVENTPAIR_H_
#include <lib/zx/eventpair.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include "src/lib/fxl/macros.h"
#include "src/sys/fuzzing/common/async-types.h"
namespace fuzzing {
constexpr zx_signals_t kSyncSignal = ZX_USER_SIGNAL_0;
constexpr zx_signals_t kStartSignal = ZX_USER_SIGNAL_1;
constexpr zx_signals_t kFinishSignal = ZX_USER_SIGNAL_2;
constexpr zx_signals_t kLeakSignal = ZX_USER_SIGNAL_3;
// This enum renames some Zircon user signals to associate them with certain actions performed by
// the engine.
enum Signal : zx_signals_t {
// Sent by the engine to the targets after it has added a process or module proxy object for them.
kSync = kSyncSignal,
// Sent by the engine to the targets at the start of a fuzzing run, and echoed by the targets back
// to the engine as acknowledgement.
kStart = kStartSignal,
// Sent by the engine to the targets at the end of a fuzzing run. Targets will echo with the same
// or with |kFinishWithLeaks|, depending on whether they suspect a memory leak.
kFinish = kFinishSignal,
// Sent by the engine to the targets at the start of a fuzzing run in which leak detection should
// be enabled. Targets will acknowledge with |kStart|.
kStartLeakCheck = kStartSignal | kLeakSignal,
// Sent by the targets to acknowledge receiving |kFinish| when a memory leak is suspected.
kFinishWithLeaks = kFinishSignal | kLeakSignal,
};
// This class wraps an eventpair to facilitate sending and asynchronously receiving signals with
// additional error-checking.
class AsyncEventPair final {
public:
explicit AsyncEventPair(ExecutorPtr executor);
~AsyncEventPair() = default;
const zx::eventpair& eventpair() const { return eventpair_; }
const ExecutorPtr& executor() const { return executor_; }
// Creates an event pair and returns one end via |out|. If this object was previously created or
// linked, it is first reset.
zx::eventpair Create();
// Takes one end of an event pair. If this object was previously paired, it is first reset.
void Pair(zx::eventpair&& eventpair);
// Returns whether the eventpair is valid and hasn't seen a "peer closed" signal.
bool IsConnected();
// Clears and sets user signals on to this end of the eventpair. Non-user signals are ignored.
// Returns an error if not connected.
__WARN_UNUSED_RESULT zx_status_t SignalSelf(zx_signals_t to_clear, zx_signals_t to_set);
// Clears and sets user signals on to the other end of the eventpair. Non-user signals are
// ignored. Returns an error if not connected.
__WARN_UNUSED_RESULT zx_status_t SignalPeer(zx_signals_t to_clear, zx_signals_t to_set);
// Returns the subset of |signals| currently set on this end of the eventpair.
zx_signals_t GetSignals(zx_signals_t signals);
// Promises to receive one or more of the requested |signals|. If the object receives a
// |ZX_EVENTPAIR_PEER_CLOSED| signal, it will return a |ZX_ERR_PEER_CLOSED| error, even if that
// signal was one of the requested |signals|.
ZxPromise<zx_signals_t> WaitFor(zx_signals_t signals);
// Resets the underlying eventpair.
void Reset();
private:
zx::eventpair eventpair_;
ExecutorPtr executor_;
fpromise::suspended_task suspended_;
Scope scope_;
FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(AsyncEventPair);
};
} // namespace fuzzing
#endif // SRC_SYS_FUZZING_COMMON_ASYNC_EVENTPAIR_H_