dfx 0.1.0
Linux-based dynamic dataflow executor
Loading...
Searching...
No Matches
Process.hpp
1// SPDX-FileCopyrightText: 2026 Vincent Leroy
2// SPDX-License-Identifier: MIT
3//
4// This file is part of dfx.
5//
6// Licensed under the MIT License. See the LICENSE file in the project root
7// for full license information.
8
9#pragma once
10
11// Standard includes
12#include <chrono>
13#include <cstdint>
14#include <functional>
15#include <optional>
16#include <string>
17#include <sys/types.h>
18#include <variant>
19#include <vector>
20
21// Project includes
23#include <dfx-fdwatch/PollerFd.hpp>
25#include <dfx-utilities/FileSystem.hpp>
27
28namespace dfx::FdWatch
29{
30class Poller;
31} // !namespace dfx::FdWatch
32
34{
59{
60 DFX_PRIVATE_STATE(Process, DFX_SUBPROCESS_LOGGER())
61
62public:
64 enum class StreamMode : std::uint8_t
65 {
71
77
83 };
84
86 enum class Which : std::uint8_t
87 {
91 };
92
94 enum class EnvMode : std::uint8_t
95 {
98 };
99
100public:
102 using NotificationCallback = std::move_only_function<void ()>;
103
106 using ReadCallback = std::move_only_function<void (std::string)>;
107
108public:
111 {
118 std::size_t maxSize = 1 * 1024 * 1024;
119 };
120
122 struct Config
123 {
125 fs::path bin;
127 std::vector<std::string> args;
129 std::vector<std::string> env;
130
132 std::optional<fs::path> cwd;
133
136
143
148
151
153 std::optional<uid_t> uid;
155 std::optional<gid_t> gid;
157 bool newSid = false;
158 };
159
160public:
177
180 {
182 int err;
183 };
184
186 struct Exited
187 {
188 int code;
189 };
190
192 struct Signaled
193 {
194 int signal;
196 };
197
205 struct ExitStatus : public std::variant<std::monostate, SpawnError, Exited, Signaled>
206 {
207 using std::variant<std::monostate, SpawnError, Exited, Signaled>::variant;
208
210 bool isSet() const noexcept { return !std::holds_alternative<std::monostate>(*this); }
212 bool isSpawnError() const noexcept { return std::holds_alternative<SpawnError>(*this); }
214 bool isExited() const noexcept { return std::holds_alternative<Exited>(*this); }
216 bool isSignaled() const noexcept { return std::holds_alternative<Signaled>(*this); }
217
219 SpawnError const & toSpawnError() const { return std::get<SpawnError>(*this); }
221 Exited const & toExited() const { return std::get<Exited>(*this); }
223 Signaled const & toSignaled() const { return std::get<Signaled>(*this); }
224 };
225
226public:
228 static constexpr auto infinite = std::chrono::milliseconds(-1);
229
230public:
239
241 Utils::BorrowedFd pidfd() const noexcept;
243 pid_t pid() const noexcept;
245 bool isRunning() const noexcept;
247 Config const & config() const noexcept;
250 fs::path const & resolvedBinPath() const noexcept;
251
253 ExitStatus const & lastExitStatus() const noexcept;
254
255public:
260 std::string takeStdout() noexcept;
265 std::string takeStderr() noexcept;
266
267public:
272 void start();
273
281 void stop(std::chrono::milliseconds timeout = infinite);
282
289 void kill();
290
293 void sendSignal(int sig);
294
305 void write(std::string data, NotificationCallback onWriteFinishedCb = nullptr);
306
319 void registerReadCallback(Which stream, ReadCallback onReadyReadCb);
320
324
334 void close(Which stream) noexcept;
335
336public:
354 static fs::path resolveProgramPath(fs::path const & bin);
355
356public:
362 static pid_t forkWithPidfd(int & pidfd) noexcept;
369 static int pidfdSendSignal(int pidfd, int sig) noexcept;
370};
371} // !namespace dfx::Subprocess
372
Macro-based enum <-> string utilities for dfx.
#define DFX_DECLARE_ENUM_STRING_FUNCTIONS(E)
Declare the enum string API (and std::formatter) for enum type E.
Definition EnumString.hpp:327
Event interest and trigger flags for file-descriptor watching (Linux/epoll).
Macros to implement the Private State (PIMPL-like) idiom with value semantics.
#define DFX_PRIVATE_STATE(Class, logger)
Declare a private implementation state for a class.
Definition PrivateState.hpp:52
#define DFX_PRIVATE_STATE_DECLARE_RULE_OF_5(Class)
Declare Rule-of-5 special member functions using the private state pattern.
Definition PrivateState.hpp:82
Abstract interface for FD-based event polling.
Definition Poller.hpp:37
StreamMode
How a standard stream of the child is wired.
Definition Process.hpp:65
@ Pipe
Stream is connected to a pipe between host and child.
Definition Process.hpp:82
@ Forward
Stream is inherited/forwarded; the host does not touch the child's fds.
Definition Process.hpp:70
@ Close
Stream is connected to /dev/null.
Definition Process.hpp:76
Which
Identifies which standard stream is being referred to.
Definition Process.hpp:87
@ Stdout
Child standard output.
Definition Process.hpp:89
@ Stdin
Child standard input.
Definition Process.hpp:88
@ Stderr
Child standard error.
Definition Process.hpp:90
pid_t pid() const noexcept
Return the child PID, or -1 if not started.
void start()
Spawn the child process and set up I/O as requested by Config.
EnvMode
How the provided environment list in Config is applied.
Definition Process.hpp:95
@ Replace
Replace the child's environment with Config::env entirely.
Definition Process.hpp:96
@ Merge
Merge Config::env into the current environment. Value provided in Config::env takes precedence.
Definition Process.hpp:97
void registerReadCallback(Which stream, ReadCallback onReadyReadCb)
Register a callback invoked when the given stream becomes readable.
void write(std::string data, NotificationCallback onWriteFinishedCb=nullptr)
Write data to the child's stdin when stdin is piped.
std::string takeStderr() noexcept
Retrieve and clear the captured stderr buffer.
void kill()
Forcefully terminate the process.
std::move_only_function< void(std::string)> ReadCallback
Callback invoked when data is available from a piped output stream.
Definition Process.hpp:106
Utils::BorrowedFd pidfd() const noexcept
Return a borrowed pidfd for the child.
static constexpr auto infinite
Convenience timeout value meaning "wait indefinitely".
Definition Process.hpp:228
static int pidfdSendSignal(int pidfd, int sig) noexcept
Send a signal to a process referred to by pidfd.
std::move_only_function< void()> NotificationCallback
Callback invoked for notifications (no arguments).
Definition Process.hpp:102
void sendSignal(int sig)
Send a signal to the child process.
ChildExecStage
Internal stage identifiers used to report where spawn/exec failed in the child. If the child cannot b...
Definition Process.hpp:164
@ SetGid
Setting the new GID.
Definition Process.hpp:169
@ DupStdout
Duplicating/redirecting stdout.
Definition Process.hpp:173
@ SigmaskUnblock
Unblocking signals before exec.
Definition Process.hpp:165
@ Execve
Executing the new program image.
Definition Process.hpp:175
@ SetSid
Setting the new session ID.
Definition Process.hpp:170
@ SetUid
Setting the new UID.
Definition Process.hpp:168
@ SetParentDeathSignal
Setting the parent-death signal (if enabled).
Definition Process.hpp:166
@ ChangeWorkingDirectory
Applying Config::cwd.
Definition Process.hpp:171
@ CheckParentAlive
Verifying parent is still alive before continuing.
Definition Process.hpp:167
@ DupStdin
Duplicating/redirecting stdin.
Definition Process.hpp:172
@ DupStderr
Duplicating/redirecting stderr.
Definition Process.hpp:174
ExitStatus const & lastExitStatus() const noexcept
Get the most recent exit status.
Config const & config() const noexcept
Access the configuration used to spawn the process.
fs::path const & resolvedBinPath() const noexcept
Resolved program path used for exec (typically absolute).
static fs::path resolveProgramPath(fs::path const &bin)
Resolve an executable name against PATH.
void stop(std::chrono::milliseconds timeout=infinite)
Request the process to stop and wait up to the given timeout.
static pid_t forkWithPidfd(int &pidfd) noexcept
Fork and obtain a pidfd for the child.
bool isRunning() const noexcept
True if the child is currently running.
std::string takeStdout() noexcept
Retrieve and clear the captured stdout buffer.
void registerTerminationCallback(NotificationCallback onChildFinishedCb)
Register a callback invoked when the child terminates or a spawn error is observed.
Process(FdWatch::Poller &poller, Config config)
Construct a process manager bound to an event poller.
void close(Which stream) noexcept
Close the host side of the specified stream (when applicable).
Non-owning wrapper around a file descriptor.
Definition BorrowedFd.hpp:33
Definition SocketClient.hpp:23
Definition Process.hpp:34
Definition Message.hpp:21
STL namespace.
Configuration for captured output buffering.
Definition Process.hpp:111
std::size_t maxSize
Maximum amount of captured data kept in memory for the corresponding stream.
Definition Process.hpp:118
Process spawn and I/O configuration.
Definition Process.hpp:123
std::optional< fs::path > cwd
Optional working directory for the child process.
Definition Process.hpp:132
StreamMode stderrMode
Child stderr wiring mode.
Definition Process.hpp:142
std::optional< uid_t > uid
Optional UID that will be used as the effective UID for the new process (requires priviledges).
Definition Process.hpp:153
StreamMode stdoutMode
Child stdout wiring mode.
Definition Process.hpp:140
CaptureConfig stderrCaptureConfig
Capture behavior for stderr when stderrMode is StreamMode::Pipe.
Definition Process.hpp:147
StreamMode stdinMode
Child stdin wiring mode.
Definition Process.hpp:138
std::vector< std::string > env
Environment entries, in "KEY=VALUE" form.
Definition Process.hpp:129
std::optional< gid_t > gid
Optional GID that will be used as the effective GID for the new process (requires priviledges).
Definition Process.hpp:155
fs::path bin
Program path (may be absolute or resolved via PATH; see resolveProgramPath()).
Definition Process.hpp:125
bool useParentDeathSignal
Whether to set a "parent death" signal for the child. PR_SET_PDEATHSIG(2const)
Definition Process.hpp:150
EnvMode envMode
Environment application mode.
Definition Process.hpp:135
std::vector< std::string > args
Arguments passed to the program (excluding argv[0]).
Definition Process.hpp:127
bool newSid
Whether to place the new process in its own session or not.
Definition Process.hpp:157
CaptureConfig stdoutCaptureConfig
Capture behavior for stdout when stdoutMode is StreamMode::Pipe.
Definition Process.hpp:145
Variant describing the last known termination state.
Definition Process.hpp:206
SpawnError const & toSpawnError() const
Access the SpawnError variant. Throws std::bad_variant_access if not that alternative.
Definition Process.hpp:219
bool isSet() const noexcept
True if a non-empty status is available.
Definition Process.hpp:210
bool isSignaled() const noexcept
True if the process was terminated by a signal.
Definition Process.hpp:216
bool isSpawnError() const noexcept
True if the child failed during spawn/exec.
Definition Process.hpp:212
Exited const & toExited() const
Access the Exited variant. Throws std::bad_variant_access if not that alternative.
Definition Process.hpp:221
Signaled const & toSignaled() const
Access the Signaled variant. Throws std::bad_variant_access if not that alternative.
Definition Process.hpp:223
bool isExited() const noexcept
True if the process exited normally.
Definition Process.hpp:214
Normal exit description.
Definition Process.hpp:187
int code
Exit code returned by the process.
Definition Process.hpp:188
Signal termination description.
Definition Process.hpp:193
bool coreDumped
Whether a core dump occurred.
Definition Process.hpp:195
int signal
Signal number that terminated the process.
Definition Process.hpp:194
Spawn failure description.
Definition Process.hpp:180
ChildExecStage stage
Stage at which the spawn failed.
Definition Process.hpp:181
int err
Error code (errno of the child at the failure point).
Definition Process.hpp:182