Subprocess wrapper with optional stdio piping/capture and event-driven callbacks.
More...
#include <dfx-subprocess/Process.hpp>
|
| enum class | StreamMode : std::uint8_t { Forward
, Close
, Pipe
} |
| | How a standard stream of the child is wired. More...
|
| enum class | Which : std::uint8_t { Stdin
, Stdout
, Stderr
} |
| | Identifies which standard stream is being referred to. More...
|
| enum class | EnvMode : std::uint8_t { Replace
, Merge
} |
| | How the provided environment list in Config is applied. More...
|
| enum class | ChildExecStage : std::uint32_t {
SigmaskUnblock
, SetParentDeathSignal
, CheckParentAlive
, ChangeWorkingDirectory
,
DupStdin
, DupStdout
, DupStderr
, Execve
} |
| | Internal stage identifiers used to report where spawn/exec failed in the child. If the child cannot be set up or exec'd, SpawnError provides both the stage and errno. More...
|
| using | NotificationCallback = std::move_only_function<void ()> |
| | Callback invoked for notifications (no arguments).
|
| using | ReadCallback = std::move_only_function<void (std::string)> |
| | Callback invoked when data is available from a piped output stream.
|
|
| | Process (FdWatch::Poller &poller, Config config) |
| | Construct a process manager bound to an event poller.
|
|
| DFX_PRIVATE_STATE_DECLARE_RULE_OF_5 (Process) |
| FdWatch::BorrowedFd | pidfd () const noexcept |
| | Return a borrowed pidfd for the child.
|
| pid_t | pid () const noexcept |
| | Return the child PID, or -1 if not started.
|
| bool | isRunning () const noexcept |
| | True if the child is currently running.
|
| 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).
|
| ExitStatus const & | lastExitStatus () const noexcept |
| | Get the most recent exit status.
|
| std::string | takeStdout () noexcept |
| | Retrieve and clear the captured stdout buffer.
|
| std::string | takeStderr () noexcept |
| | Retrieve and clear the captured stderr buffer.
|
| void | start () |
| | Spawn the child process and set up I/O as requested by Config.
|
| void | stop (std::chrono::milliseconds timeout=infinite) |
| | Request the process to stop and wait up to the given timeout.
|
| void | kill () |
| | Forcefully terminate the process.
|
| void | sendSignal (int sig) |
| | Send a signal to the child process.
|
| void | write (std::string data, NotificationCallback onWriteFinishedCb=nullptr) |
| | Write data to the child's stdin when stdin is piped.
|
| void | registerReadCallback (Which stream, ReadCallback onReadyReadCb) |
| | Register a callback invoked when the given stream becomes readable.
|
| void | registerTerminationCallback (NotificationCallback onChildFinishedCb) |
| | Register a callback invoked when the child terminates or a spawn error is observed.
|
| void | close (Which stream) noexcept |
| | Close the host side of the specified stream (when applicable).
|
|
| static fs::path | resolveProgramPath (fs::path const &bin) |
| | Resolve an executable name against PATH.
|
| static pid_t | forkWithPidfd (int &pidfd) noexcept |
| | Fork and obtain a pidfd for the child.
|
| static int | pidfdSendSignal (int pidfd, int sig) noexcept |
| | Send a signal to a process referred to by pidfd.
|
|
| static constexpr auto | infinite = std::chrono::milliseconds(-1) |
| | Convenience timeout value meaning "wait indefinitely".
|
Subprocess wrapper with optional stdio piping/capture and event-driven callbacks.
Process spawns and manages a child process described by a Config, and integrates with an external fd event loop via dfx::FdWatch::Poller.
It supports:
- Selecting how stdin/stdout/stderr are handled (forwarded, closed to /dev/null, or piped).
- Capturing stdout/stderr into internal buffers when piping is enabled.
- Registering callbacks for readability (stdout/stderr), write completion, and termination.
- Stopping a child gracefully with a timeout and escalating if needed.
Typical usage:
- Create with a poller and a configuration.
- Register read/termination callbacks (optional).
- Call start().
- Optionally write to stdin when stdin is piped.
- Read captured output via callbacks and/or takeStdout() / takeStderr().
- Stop/kill as needed.
- Note
- By design once a Process is created you cannot change its Config. If you need to then you have to do something like p = Process(poller, newConfig);
◆ NotificationCallback
Callback invoked for notifications (no arguments).
◆ ReadCallback
Callback invoked when data is available from a piped output stream.
- Parameters
-
| data | Newly read chunk of data (not necessarily line-delimited). |
◆ ChildExecStage
Internal stage identifiers used to report where spawn/exec failed in the child. If the child cannot be set up or exec'd, SpawnError provides both the stage and errno.
| Enumerator |
|---|
| SigmaskUnblock | Unblocking signals before exec.
|
| SetParentDeathSignal | Setting the parent-death signal (if enabled).
|
| CheckParentAlive | Verifying parent is still alive before continuing.
|
| ChangeWorkingDirectory | Applying Config::cwd.
|
| DupStdin | Duplicating/redirecting stdin.
|
| DupStdout | Duplicating/redirecting stdout.
|
| DupStderr | Duplicating/redirecting stderr.
|
| Execve | Executing the new program image.
|
◆ EnvMode
How the provided environment list in Config is applied.
| Enumerator |
|---|
| Replace | Replace the child's environment with Config::env entirely.
|
| Merge | Merge Config::env into the current environment. Value provided in Config::env takes precedence.
|
◆ StreamMode
How a standard stream of the child is wired.
| Enumerator |
|---|
| Forward | Stream is inherited/forwarded; the host does not touch the child's fds.
- stdin, input is read from the parent’s stdin.
- stdout/stderr, output goes to the parent’s stdout/stderr.
|
| Close | Stream is connected to /dev/null.
- stdin: immediate EOF to the child.
- stdout/stderr: discards all output.
|
| Pipe | Stream is connected to a pipe between host and child.
- stdin: host can write into the child’s stdin.
- stdout/stderr: host can read from the child’s output.
|
◆ Which
Identifies which standard stream is being referred to.
| Enumerator |
|---|
| Stdin | Child standard input.
|
| Stdout | Child standard output.
|
| Stderr | Child standard error.
|
◆ Process()
Construct a process manager bound to an event poller.
- Parameters
-
| poller | Poller used to watch internal fds (pipes/pidfd) and dispatch callbacks. |
| config | Spawn configuration. |
- Note
- The process is not started automatically; call start().
◆ close()
| void dfx::Subprocess::Process::close |
( |
Which | stream | ) |
|
|
noexcept |
Close the host side of the specified stream (when applicable).
- Parameters
-
- Closing stdin signals EOF to the child.
- Closing stdout/stderr stops further reads on the host side.
This operation only make sense if the associated stream is in StreamMode::Pipe mode If not then this operation is a no-op.
◆ config()
| Config const & dfx::Subprocess::Process::config |
( |
| ) |
const |
|
noexcept |
Access the configuration used to spawn the process.
◆ forkWithPidfd()
| pid_t dfx::Subprocess::Process::forkWithPidfd |
( |
int & | pidfd | ) |
|
|
staticnoexcept |
Fork and obtain a pidfd for the child.
- Parameters
-
| [out] | pidfd | On success, receives a pidfd referring to the child. |
- Returns
- In the parent: child's PID; in the child: 0; on error: -1 (typical fork semantics).
◆ isRunning()
| bool dfx::Subprocess::Process::isRunning |
( |
| ) |
const |
|
noexcept |
True if the child is currently running.
◆ kill()
| void dfx::Subprocess::Process::kill |
( |
| ) |
|
Forcefully terminate the process.
A SIGKILL signal is immediately sent to the process which is then immediately waited for. Meaning that after this call isRunning() returns false. Calling kill on a non-running child is a no-op.
◆ lastExitStatus()
| ExitStatus const & dfx::Subprocess::Process::lastExitStatus |
( |
| ) |
const |
|
noexcept |
Get the most recent exit status.
◆ pid()
| pid_t dfx::Subprocess::Process::pid |
( |
| ) |
const |
|
noexcept |
Return the child PID, or -1 if not started.
◆ pidfd()
Return a borrowed pidfd for the child.
◆ pidfdSendSignal()
| int dfx::Subprocess::Process::pidfdSendSignal |
( |
int | pidfd, |
|
|
int | sig ) |
|
staticnoexcept |
Send a signal to a process referred to by pidfd.
- Parameters
-
| pidfd | Process file descriptor. |
| sig | Signal number. |
- Returns
- 0 on success or -1 on error (typical errno-style API).
◆ registerReadCallback()
| void dfx::Subprocess::Process::registerReadCallback |
( |
Which | stream, |
|
|
ReadCallback | onReadyReadCb ) |
Register a callback invoked when the given stream becomes readable.
- Parameters
-
| stream | Stream to observe (Which::Stdout or Which::Stderr). |
| onReadyReadCb | Callback receiving newly read chunks of data. Can be nullptr. |
This function will throw an exception if the specified stream is Which::Stdin.
If this function is called while the child is running and the previous callback was nullptr, then all accumulated until now will be passed to the callback in accordance with the CaptureConfig::maxSize
- Note
- Stream must be configured as StreamMode::Pipe for readability notifications.
◆ registerTerminationCallback()
| void dfx::Subprocess::Process::registerTerminationCallback |
( |
NotificationCallback | onChildFinishedCb | ) |
|
Register a callback invoked when the child terminates or a spawn error is observed.
- Parameters
-
| onChildFinishedCb | Callback invoked once termination is detected. Can be nullptr. |
◆ resolvedBinPath()
| fs::path const & dfx::Subprocess::Process::resolvedBinPath |
( |
| ) |
const |
|
noexcept |
◆ resolveProgramPath()
| fs::path dfx::Subprocess::Process::resolveProgramPath |
( |
fs::path const & | bin | ) |
|
|
static |
Resolve an executable name against PATH.
- Parameters
-
- Returns
- If
bin contains a '/' character, returns bin unchanged (no existence/permission checks).
- Otherwise, searches the current PATH (as returned by
getPath()) for an executable regular file named bin and returns the first match.
- If no match is found, returns an empty path ({ }).
PATH is split on ':'; per POSIX, an empty PATH element is treated as the current directory ("./").
A candidate is accepted only if:
faccessat(..., X_OK, AT_EACCESS) succeeds, and
stat() succeeds and indicates a regular file (S_ISREG).
- Note
- This function does not resolve symlinks or canonicalize paths; it returns the path as constructed.
◆ sendSignal()
| void dfx::Subprocess::Process::sendSignal |
( |
int | sig | ) |
|
Send a signal to the child process.
- Parameters
-
| sig | Signal number (e.g., SIGTERM, SIGINT). |
◆ start()
| void dfx::Subprocess::Process::start |
( |
| ) |
|
Spawn the child process and set up I/O as requested by Config.
- Note
- Spawn failures happening in the child prior to exec are reported via lastExitStatus() as SpawnError.
◆ stop()
| void dfx::Subprocess::Process::stop |
( |
std::chrono::milliseconds | timeout = infinite | ) |
|
Request the process to stop and wait up to the given timeout.
- Parameters
-
| timeout | Maximum time to wait. Use infinite to wait indefinitely. |
A SIGTERM signal is sent to the child. If after timeout the child still hasn't stop, then kill() is called. Calling stop on a non-running child is a no-op.
◆ takeStderr()
| std::string dfx::Subprocess::Process::takeStderr |
( |
| ) |
|
|
noexcept |
Retrieve and clear the captured stderr buffer.
Meaningful only when Config::stderrMode is StreamMode::Pipe and no read callback is registered. If stderr is not being captured, this returns an empty string.
◆ takeStdout()
| std::string dfx::Subprocess::Process::takeStdout |
( |
| ) |
|
|
noexcept |
Retrieve and clear the captured stdout buffer.
Meaningful only when Config::stdoutMode is StreamMode::Pipe and no read callback is registered. If stdout is not being captured, this returns an empty string.
◆ write()
| void dfx::Subprocess::Process::write |
( |
std::string | data, |
|
|
NotificationCallback | onWriteFinishedCb = nullptr ) |
Write data to the child's stdin when stdin is piped.
- Parameters
-
| data | Data to write (moved into internal buffers as needed). |
| onWriteFinishedCb | Optional callback invoked once the write has completed. |
It is perfectly valid to call this function before start(). In this case the data is buffered and will be sent as soon as the child is ready to receive them.
If Config::stdinMode is not StreamMode::Pipe, this function will throw an exception.
◆ infinite
| auto dfx::Subprocess::Process::infinite = std::chrono::milliseconds(-1) |
|
staticconstexpr |
Convenience timeout value meaning "wait indefinitely".
The documentation for this class was generated from the following file: