pub struct PayloadHandle { /* private fields */ }Expand description
Handle to a background payload spawned via
PayloadRun::spawn. Wraps a guest-local
std::process::Child; wait / kill both consume the handle
and return the collected metrics + assertion verdict.
Drop behavior: if the handle is dropped without wait/kill,
the child and every process it forked are SIGKILLed via the
process group headed by the child, then the child is reaped with
child.wait(), and a stderr warning is emitted so the test
author sees the implicit drop. The process-group kill reaches
every descendant of multi-process payloads (stress-ng, schbench
worker mode, fio --numjobs); without it the orphans keep
stdout/stderr open, block wait_and_capture, and lose metrics.
When multiple handles are active, sidecar entries appear in
finalization order (the order .wait(), .kill(), or
.try_wait() returning Ok(Some(..)) are called), not spawn
order. .try_wait() only records on its terminal branch; an
Ok(None) return keeps the handle live and defers the sidecar
write to the next terminal call.
Implementations§
Source§impl PayloadHandle
impl PayloadHandle
Sourcepub fn payload_name(&self) -> &'static str
pub fn payload_name(&self) -> &'static str
Name of the Payload this handle was spawned from — i.e.
the identity key used by step-level ops to address a running
payload. Step-local ops (Op::WaitPayload,
Op::KillPayload)
match handles by this name.
Sourcepub fn pid(&self) -> Option<u32>
pub fn pid(&self) -> Option<u32>
Live child’s OS-level pid, or None once wait/kill/
try_wait has consumed the child.
Integration tests that spawn a workload and then need to
target it with a second tool (for example the jemalloc-TLS
probe in tests/jemalloc_probe_tests.rs, which passes the
workload’s pid to ktstr-jemalloc-probe --pid) read this
value between spawn and wait/kill/try_wait. The
internal fork-descendant reap test also uses it to probe
the process group via killpg(_, 0) after kill() without
reaching into the private child field.
Sourcepub fn wait(self) -> Result<(AssertResult, PayloadMetrics)>
pub fn wait(self) -> Result<(AssertResult, PayloadMetrics)>
Block until the child exits naturally, then extract metrics
and evaluate checks, matching the foreground .run() return
shape.
Metrics are also recorded to the per-test sidecar via the SHM ring; the returned tuple is a convenience view of the same values.
Sourcepub fn kill(self) -> Result<(AssertResult, PayloadMetrics)>
pub fn kill(self) -> Result<(AssertResult, PayloadMetrics)>
SIGKILL the child and every process it forked, reap it, and return whatever stdout+stderr was captured along with the process exit code. Suitable for time-boxed background loads.
The signal is delivered via killpg(child_pid, SIGKILL)
rather than child.kill() because build_command places the
payload at the head of its own process group. Multi-process
payloads (stress-ng, schbench worker mode, fio –numjobs) fork
descendants that keep stdout/stderr open; killing only the
head would orphan those writers and block
wait_and_capture forever, losing every metric.
Metrics are also recorded to the per-test sidecar via the SHM ring; the returned tuple is a convenience view of the same values.
Sourcepub fn try_wait(&mut self) -> Result<Option<(AssertResult, PayloadMetrics)>>
pub fn try_wait(&mut self) -> Result<Option<(AssertResult, PayloadMetrics)>>
Non-blocking check for exit without consuming the handle.
Returns Ok(Some((result, metrics))) once the child has
exited and output is drained; Ok(None) while still
running. The handle remains live on Ok(None).
On the terminal Ok(Some(..)) return, metrics are also
recorded to the per-test sidecar via the SHM ring; the
returned tuple is a convenience view of the same values.
Trait Implementations§
Source§impl Debug for PayloadHandle
impl Debug for PayloadHandle
Source§impl Drop for PayloadHandle
Drop-safety net for handles that fall out of scope without
going through PayloadHandle::wait, PayloadHandle::kill,
or PayloadHandle::try_wait (the three paths that
.take() the child normally). Drop routes the process group
through kill_payload_process_group — the SAME kill path the
explicit kill() method uses — so there is no redundant
child.kill() call: the killpg + single-pid SIGKILL inside
kill_payload_process_group is belt-and-suspenders-by-design
(see its doc for the pre-exec ESRCH race rationale), not
two independent kills stacked. child.wait() reaps the
zombie so the pid slot is freed even on the “dropped without
consume” path, and the one-shot eprintln tells the operator
metrics were lost.
impl Drop for PayloadHandle
Drop-safety net for handles that fall out of scope without
going through PayloadHandle::wait, PayloadHandle::kill,
or PayloadHandle::try_wait (the three paths that
.take() the child normally). Drop routes the process group
through kill_payload_process_group — the SAME kill path the
explicit kill() method uses — so there is no redundant
child.kill() call: the killpg + single-pid SIGKILL inside
kill_payload_process_group is belt-and-suspenders-by-design
(see its doc for the pre-exec ESRCH race rationale), not
two independent kills stacked. child.wait() reaps the
zombie so the pid slot is freed even on the “dropped without
consume” path, and the one-shot eprintln tells the operator
metrics were lost.
Auto Trait Implementations§
impl Freeze for PayloadHandle
impl RefUnwindSafe for PayloadHandle
impl !Send for PayloadHandle
impl !Sync for PayloadHandle
impl Unpin for PayloadHandle
impl UnwindSafe for PayloadHandle
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more