blob: 15e363c7c167b0fae6f66a8d480206a0098172ff [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_DEVELOPER_DEBUG_E2E_TESTS_FFX_DEBUG_AGENT_BRIDGE_H_
#define SRC_DEVELOPER_DEBUG_E2E_TESTS_FFX_DEBUG_AGENT_BRIDGE_H_
#include <filesystem>
#include <string>
#include "src/developer/debug/zxdb/common/err.h"
#include "src/lib/fxl/macros.h"
namespace zxdb {
// This class is to RAII the sub-process for FFX that will spawn the socket
// connections the host side of the debugger needs in order to speak to the FIDL
// protocol implemented in DebugAgent.
//
// Specifically, this will:
// 1. Create a UNIX pipe with two file descriptors.
// 2. Fork the process and exec `ffx debug connect --agent-only`.
// 3. The write end of the pipe will go to the child and dup STDOUT.
// 4. The read end of the pipe will go to the parent.
// 5. Close both the read and write ends of the pipe in the parent.
// 6. Close both the read and write ends of the pipe in the child.
// 7. After all tests have run, this will be destructed and issue a SIGTERM to
// the ffx command to clean up the DebugAgent socket and files.
class FfxDebugAgentBridge {
public:
FfxDebugAgentBridge();
~FfxDebugAgentBridge();
// Unconditionally shutdown the bridge, and cleanup the child process. This function is signal
// safe and can be called from a signal handler.
void Cleanup();
// It is expected that this method is called once per test executable, and that many test cases
// can be run with this object constructed before all cases and destructed after all cases.
// Calling this method will involve fork-ing and exec-ing `ffx debug connect --agent-only`
// with additional necessary parameters in infra builds to determine the proper target from the
// environment. Locally, it is assumed that `fx set-device` has been used to configure which
// device to use.
Err Init();
std::string_view GetDebugAgentSocketPath() const { return socket_path_; }
// Get the global instance or nullptr.
static FfxDebugAgentBridge* Get();
private:
// Fork the child process with the pipe file descriptors configured to send
// the STDOUT of child to the write end of the pipe and the parent to wait
// for the read end of the pipe.
//
// Returns an Err containing the stringified errno value on failure.
Err SetupPipeAndFork();
// Reads the path to the UNIX socket created by the ffx sub-process from
// |pipe_read_end_|.
//
// Returns an Err containing the stringified errno value on failure.
Err ReadDebugAgentSocketPath();
// Close all remaining open file descriptors, and send SIGTERM to the child
// process.
//
// Returns an Err containing the stringified errno value on failure.
Err CleanupChild() const;
int pipe_read_end_ = 0;
int pipe_write_end_ = 0;
int child_pid_ = 0;
std::string socket_path_;
std::filesystem::path ffx_isolate_dir_;
FXL_DISALLOW_COPY_AND_ASSIGN(FfxDebugAgentBridge);
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_E2E_TESTS_FFX_DEBUG_AGENT_BRIDGE_H_