docs(comments): rewrite comments across all crates to the guidelines
Sweep every first-party crate source (1956 .rs files) to the project comment guidelines: delete redundant restatements, decorative banners, change narration, and end-of-line comments; keep and tighten the crucial ones (invariants, bug rationale, SAFETY blocks, ported-source attribution). No functional code changed. Every edit is proven comment-only against the prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a separate doctest-fence check. Where removing a comment made rustfmt or clippy want to re-lay-out adjacent code, the minimal triggering comment is restored so code tokens stay byte-identical. Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy --workspace --all-targets (0 warnings). Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for these guidelines (flags banners, end-of-line comments, change narration, and commented-out code).
This commit is contained in:
@@ -2,8 +2,7 @@
|
||||
//! to a wall-clock budget, and reap the whole process group on a breach.
|
||||
//!
|
||||
//! Used by both the optional [`crate::MmdcEngine`] (which shells out to
|
||||
//! `mmdc`/headless-Chromium) and the pager's out-of-process render child (a
|
||||
//! short-lived re-exec of the pager that renders one diagram in isolation). The
|
||||
//! `mmdc`/headless-Chromium) and the pager's out-of-process render child. The
|
||||
//! timeout is a *real* process kill, not a soft signal: a panic under
|
||||
//! `panic = "abort"` or a runaway render in the child is contained because the
|
||||
//! parent kills and reaps it.
|
||||
@@ -57,14 +56,10 @@ pub fn run_with_timeout(
|
||||
) -> Result<(), SubprocessError> {
|
||||
let mut child = spawn_with_etxtbsy_retry(&mut cmd).map_err(SubprocessError::Spawn)?;
|
||||
|
||||
// Feed stdin from a scoped thread so a child that stops reading can't wedge
|
||||
// a `write_all` of a large (up to the source-size cap) payload and deadlock
|
||||
// the wait below. On timeout we kill the child, which EOF/EPIPEs the writer.
|
||||
let stdin = child.stdin.take();
|
||||
|
||||
// A payload with no piped stdin would be silently dropped (the caller forgot
|
||||
// `cmd.stdin(Stdio::piped())`). Both in-tree callers pipe correctly; flag the
|
||||
// foot-gun loudly in debug and at least log it in release.
|
||||
// A payload with no piped stdin is silently dropped, so flag that caller
|
||||
// mistake loudly in debug and at least log it in release.
|
||||
if stdin_payload.is_some() && stdin.is_none() {
|
||||
tracing::warn!(
|
||||
target: "mermaid",
|
||||
@@ -75,11 +70,14 @@ pub fn run_with_timeout(
|
||||
"run_with_timeout: stdin_payload supplied but cmd.stdin is not piped (payload dropped)"
|
||||
);
|
||||
}
|
||||
// `scope` joins the writer before returning, so the writer must always be
|
||||
// able to finish: a child that stops reading is killed by `wait_and_reap`,
|
||||
// which EOF/EPIPEs the pending `write_all`.
|
||||
std::thread::scope(|scope| {
|
||||
if let (Some(mut sink), Some(payload)) = (stdin, stdin_payload) {
|
||||
scope.spawn(move || {
|
||||
use std::io::Write as _;
|
||||
// Errors are expected if the child exits/dies first; ignore them.
|
||||
// Expected to fail if the child exits first; nothing to report.
|
||||
let _ = sink.write_all(payload);
|
||||
// Dropping `sink` closes the pipe so the child observes EOF.
|
||||
});
|
||||
@@ -96,8 +94,7 @@ pub fn run_with_timeout(
|
||||
/// is close-on-exec but only closes at the child's own `execve`, leaving a
|
||||
/// fork→execve window during which our `execve` of a freshly-written binary can
|
||||
/// race. It is transient and clears within milliseconds, so retry a few times
|
||||
/// with a short backoff. (No-op on the steady-state path; only the failing
|
||||
/// transient case changes behaviour.)
|
||||
/// with a short backoff.
|
||||
fn spawn_with_etxtbsy_retry(cmd: &mut Command) -> std::io::Result<Child> {
|
||||
const MAX_ATTEMPTS: u32 = 5;
|
||||
let mut attempt = 0;
|
||||
@@ -121,14 +118,13 @@ fn spawn_with_etxtbsy_retry(cmd: &mut Command) -> std::io::Result<Child> {
|
||||
/// that spawned grandchildren can't orphan them.
|
||||
fn wait_and_reap(child: &mut Child, timeout: Duration) -> Result<(), SubprocessError> {
|
||||
match child.wait_timeout(timeout) {
|
||||
// `wait_timeout` already reaped the direct child on these two branches,
|
||||
// but it was its own detached group leader: SIGKILL the group's pgid so
|
||||
// any grandchildren (e.g. an opt-in MmdcEngine's headless Chromium) are
|
||||
// torn down regardless of exit code. The pgid stays valid while a
|
||||
// grandchild is alive (the case that matters); for the grandchild-less
|
||||
// render child the leader is already gone, so killpg is a harmless no-op
|
||||
// (ESRCH). The full `reap()` is unneeded — the direct child is already
|
||||
// reaped, so `child.kill()`/`wait()` would be redundant.
|
||||
// On these two branches `wait_timeout` already reaped the direct child,
|
||||
// so `reap()` would be redundant — but the child was its own detached
|
||||
// group leader, so still SIGKILL the pgid to tear down grandchildren
|
||||
// (e.g. an opt-in MmdcEngine's headless Chromium) regardless of exit
|
||||
// code. The pgid stays valid while a grandchild is alive, the case that
|
||||
// matters; with no grandchildren the leader is gone and killpg is a
|
||||
// harmless ESRCH no-op.
|
||||
Ok(Some(status)) if status.success() => {
|
||||
reap_process_group(child);
|
||||
Ok(())
|
||||
@@ -141,8 +137,8 @@ fn wait_and_reap(child: &mut Child, timeout: Duration) -> Result<(), SubprocessE
|
||||
reap(child);
|
||||
Err(SubprocessError::Timeout)
|
||||
}
|
||||
// waitpid failed; the child may still be running, so reap it too — the
|
||||
// same teardown as the timeout branch (don't leak the child tree).
|
||||
// waitpid failed, so the child may still be running: same teardown as
|
||||
// the timeout branch rather than leaking the child tree.
|
||||
Err(e) => {
|
||||
reap(child);
|
||||
Err(SubprocessError::Wait(e))
|
||||
@@ -227,11 +223,9 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// A large stdin payload (bigger than any OS pipe buffer) must be delivered
|
||||
/// through `run_with_timeout`'s own scoped writer without deadlocking the
|
||||
/// wait — the whole reason the writer is a scoped thread. We point `cat` at a
|
||||
/// file (its stdout) so we can prove every byte was consumed, and assert the
|
||||
/// call returns `Ok(())` promptly rather than hitting the timeout.
|
||||
/// A payload larger than any OS pipe buffer, the case the scoped writer
|
||||
/// exists for. `cat`'s stdout goes to a file so the drained byte count
|
||||
/// proves the whole payload was delivered and consumed.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn large_stdin_payload_is_delivered_without_deadlock() {
|
||||
@@ -256,8 +250,6 @@ mod tests {
|
||||
start.elapsed() < Duration::from_secs(5),
|
||||
"must return after the drain, not after the full timeout",
|
||||
);
|
||||
// `cat` copies all of stdin to the file → proves the whole payload was
|
||||
// both delivered and consumed via the real scoped writer.
|
||||
let drained = std::fs::metadata(&sink).expect("sink metadata").len();
|
||||
assert_eq!(
|
||||
drained,
|
||||
@@ -266,7 +258,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// `reap` actually terminates the spawned process group.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn reap_terminates_the_process() {
|
||||
@@ -278,7 +269,7 @@ mod tests {
|
||||
|
||||
reap(&mut child);
|
||||
|
||||
// After SIGKILL + wait, the pid no longer names a live process.
|
||||
// Signal 0 is an existence probe: ESRCH means the pid is gone.
|
||||
assert_eq!(unsafe { libc::kill(pid, 0) }, -1);
|
||||
assert_eq!(
|
||||
std::io::Error::last_os_error().raw_os_error(),
|
||||
@@ -294,12 +285,9 @@ mod tests {
|
||||
assert!(matches!(r, Err(SubprocessError::Spawn(_))), "got {r:?}");
|
||||
}
|
||||
|
||||
/// The dropped-stdin-payload guard fires when a caller passes a payload but
|
||||
/// forgets `cmd.stdin(Stdio::piped())`: the `debug_assert!` turns that silent
|
||||
/// foot-gun into a hard failure. Gated on `debug_assertions` because that is
|
||||
/// exactly when the assert is active (release keeps only the `warn`). `true`
|
||||
/// exits at once; `detached` sets stdin to null (not piped), so the payload
|
||||
/// would be dropped and the guard must catch it.
|
||||
/// `detached` sets stdin to null rather than piped, so the payload would be
|
||||
/// silently dropped and the `debug_assert!` guard must catch it. Gated on
|
||||
/// `debug_assertions` because release builds keep only the `warn`.
|
||||
#[cfg(all(unix, debug_assertions))]
|
||||
#[test]
|
||||
#[should_panic(expected = "stdin_payload supplied but cmd.stdin is not piped")]
|
||||
|
||||
Reference in New Issue
Block a user