mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-07-12 03:12:11 +02:00
fix(bench): harden the harness — EINTR retry, loud setrlimit failure, cfg(unix) guard
Greptile review follow-ups: wait4 now retries on EINTR (a delivered signal previously panicked the harness mid-run via the reaped-pid assert); a failed setrlimit warns on inherited stderr instead of silently running the child uncapped while the parent JSON records the requested cap; and the Unix-only syscalls are cfg(unix)-gated with an inert Windows stub main so cargo bench compiles everywhere.
This commit is contained in:
parent
8195a3ed72
commit
c6b4a6ce2b
1 changed files with 29 additions and 3 deletions
|
|
@ -23,7 +23,12 @@
|
||||||
//! ignores RLIMIT_AS — the cap variant is primarily a Linux tool, while
|
//! ignores RLIMIT_AS — the cap variant is primarily a Linux tool, while
|
||||||
//! peak-RSS reporting works everywhere).
|
//! peak-RSS reporting works everywhere).
|
||||||
|
|
||||||
|
// The harness is Unix-only (wait4/rusage/setrlimit); a Windows host gets an
|
||||||
|
// inert stub so `cargo bench`/`cargo build --benches` still compile there.
|
||||||
|
#![cfg_attr(not(unix), allow(dead_code, unused_imports))]
|
||||||
|
|
||||||
#[path = "../tests/helpers/mod.rs"]
|
#[path = "../tests/helpers/mod.rs"]
|
||||||
|
#[cfg(unix)]
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
|
|
@ -131,6 +136,12 @@ impl Args {
|
||||||
// Parent: spawn child, reap with wait4, merge rusage into the JSON record
|
// Parent: spawn child, reap with wait4, merge rusage into the JSON record
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
fn main() {
|
||||||
|
eprintln!("the scenario harness requires a Unix platform (wait4/rusage/setrlimit)");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
if args.scenario.is_empty() {
|
if args.scenario.is_empty() {
|
||||||
|
|
@ -211,7 +222,14 @@ fn run_once(args: &Args, run: usize) -> serde_json::Value {
|
||||||
fn wait4_rusage(pid: i32) -> (i64, u64) {
|
fn wait4_rusage(pid: i32) -> (i64, u64) {
|
||||||
let mut status: libc::c_int = 0;
|
let mut status: libc::c_int = 0;
|
||||||
let mut rusage: libc::rusage = unsafe { std::mem::zeroed() };
|
let mut rusage: libc::rusage = unsafe { std::mem::zeroed() };
|
||||||
let reaped = unsafe { libc::wait4(pid, &mut status, 0, &mut rusage) };
|
// Retry on EINTR: a delivered signal (SIGTERM from the shell, SIGCHLD
|
||||||
|
// from an unrelated child) interrupts the blocking wait with -1.
|
||||||
|
let reaped = loop {
|
||||||
|
let r = unsafe { libc::wait4(pid, &mut status, 0, &mut rusage) };
|
||||||
|
if r != -1 || std::io::Error::last_os_error().raw_os_error() != Some(libc::EINTR) {
|
||||||
|
break r;
|
||||||
|
}
|
||||||
|
};
|
||||||
assert_eq!(reaped, pid, "wait4 reaped unexpected pid");
|
assert_eq!(reaped, pid, "wait4 reaped unexpected pid");
|
||||||
let exit: i64 = if libc::WIFEXITED(status) {
|
let exit: i64 = if libc::WIFEXITED(status) {
|
||||||
libc::WEXITSTATUS(status) as i64
|
libc::WEXITSTATUS(status) as i64
|
||||||
|
|
@ -238,8 +256,16 @@ fn run_child(args: &Args) {
|
||||||
rlim_max: cap_mb * 1024 * 1024,
|
rlim_max: cap_mb * 1024 * 1024,
|
||||||
};
|
};
|
||||||
// RLIMIT_AS is enforced on Linux; macOS frequently ignores it. Applied
|
// RLIMIT_AS is enforced on Linux; macOS frequently ignores it. Applied
|
||||||
// best-effort everywhere so the same command line works on both.
|
// best-effort everywhere so the same command line works on both — but
|
||||||
unsafe { libc::setrlimit(libc::RLIMIT_AS, &cap) };
|
// a FAILED setrlimit must be loud (stderr is inherited): the parent's
|
||||||
|
// JSON records the requested cap, and silently running uncapped would
|
||||||
|
// misrepresent the test conditions.
|
||||||
|
if unsafe { libc::setrlimit(libc::RLIMIT_AS, &cap) } != 0 {
|
||||||
|
eprintln!(
|
||||||
|
"WARNING: setrlimit(RLIMIT_AS, {cap_mb} MiB) failed ({}); child runs UNCAPPED",
|
||||||
|
std::io::Error::last_os_error()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue