Bound crawler and tool probes through one spawn deadline (#845) - #886
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A version-manager shim that never answers (`gem`, `python3`, `npm`, `composer` behind rbenv/asdf, a Ruby waiting on a network gem home) used to hang `scan`, `apply`, `vex` and every other crawling command forever with no output: the crawler probes waited on `output()` with no deadline. Every probe now runs through one `utils::process::output_within` primitive: null stdin, captured stdout, dropped stderr, and the child killed and reaped at the deadline without waiting on a grandchild that still holds the pipe. Crawler probes get the same 10 s budget that the Pipenv and Hatch version probes and the self-update `--version` check already used, and those three sites drop their hand-rolled `tokio::time::timeout` + `kill_on_drop` blocks for it. Refs #845. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
`main` fails `utils::digest::tests::production_digests_go_through_the_ helpers` because #646 left inline sha1/sha256 calls in `gradle_cache.rs`, `jvm_jar.rs` and `sidecars/maven.rs`, which turns `test`, `test-release` and `coverage` red on every PR. This is #878's change verbatim; it no-ops once #878 merges. Assisted-by: Claude Code:claude-opus-5-5
|
[agent] The cancelled Generated by Claude Code |
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7b2eabd. Configure here.
|
[agent] Generated by Claude Code |
|
[agent] Update on This isn't this PR's. Every recent Generated by Claude Code |
|
[agent] Generated by Claude Code |
|
[agent] Ready for review at Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #845
Summary
Every crawler probe (
gem env gemdir,python3 --version,npm root -g,composer global config home, ...) now runs under a 10 s deadline through oneutils::process::output_withinprimitive. A wedged toolchain shim used to hangscan, and every other crawling command, forever with no output. The three sites that hand-rolled their owntokio::time::timeout+kill_on_drop(pipenv, hatch, self-updatesanity_exec) now use the same primitive, and their inline blocks are deleted.Why
doc/07-infra-agent.md(process spawning).CommandRunnerandnpm_dirslices reuse the primitive), D ≈3 (three duplicate timeout blocks plus the unbounded runner, all on one primitive), R M. Score ≈5.run_resolvedinutils/process.rs, so it fixes every probe without editing the crawler files that Fix hosted gem redirect ignoring Bundler mirror.all (#681) #684, sbt, Mill and scala-cli support in agent, hosted and vendored modes #690, Fix Hatch environments being invisible to stale-install checks and VEX (#335) #700 and Fix gem pair model ignoring custom lockfile and Bundler 1 twins (#749, #751) #768 change.What changed
utils::process::output_within(Command, budget) -> Result<Output, BoundedError>: null stdin, captured stdout, discarded stderr. stdout is read on a thread underrecv_timeout, then the child's exit is polled until the deadline. At the deadline the child is killed and reaped, and the call returnsTimedOutwithout waiting for a grandchild that still holds the pipe (a#!/bin/shshim'ssleep).PROBE_TIMEOUT= 10 s. That is the budget pipenv, hatch andsanity_execalready used.run_resolved, behindSystemCommandRunnerandGlobalProbeRunner, goes throughoutput_within. A probe that times out answersNone("no information"), the same as a failed probe, and logs one--debugline.pipenv::installed_major,pypi_hatch::require_environment_context_support_withandupdate::download::sanity_execbuild astd::process::Commandand run it throughrun_blocking(output_within).sanity_execkeeps its ETXTBSY retry loop around the call and its "hung during its --version self-check" error.7b2eabd): Route Gradle digests through utils::digest #878's fix, verbatim, somain's failing digest ratchet passes here. It moves the inline digests ingradle_cache.rs,jvm_jar.rsandsidecars/maven.rsontoutils::digest, and no-ops once Route Gradle digests through utils::digest #878 merges.Deleted
Refactor commit only (excluding the #878 port): 4 files, +229 / −34.
tokio::time::timeout(..., cmd.output())+kill_on_dropblocks and the unboundedcommand.output()inrun_resolved.Behavior
sanity_execalready nulled it.Test evidence
utils::process:a_hung_probe_answers_none_within_its_budget: agemshim that runsexec sleep 30, under a 300 ms budget. This can't be expressed onmain, which has no budget.output_within_does_not_wait_for_a_grandchild_holding_stdout.output_within_reports_status_stdout_and_spawn_errors: stdout, stderr dropped, nonzero exit, null stdin, missing program.pypi_hatch:a_hung_hatch_is_refused_within_the_probe_budget.sanity_exec(hang, ETXTBSY retry, wrong program) and process tests still pass.cargo test -p socket-patch-core --lib: everything passes except the 4 tests that fail onmaintoo because the sandbox runs as root (copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_…,pypi_requirements::wire_failure_rolls_back_…).utils::digest::tests::production_digests_go_through_the_helpersis red onmain@9c43dfcand green here after the Route Gradle digests through utils::digest #878 port.cargo test -p socket-patch-cli --all-features --test in_process_gem_apply --test cli_global_args --test in_process_alternate_installers: all pass.cargo clippy --workspace --all-features -- -D warnings: clean.rack 2.2.8), with agemshim onPATHthat logs its args and runsexec sleep 3600, and the API pointed at a closed port.scan --jsonexits 1 after 10 s with the full JSON envelope (scannedPackages: 1). The shim log showsenv gemdirandenv gempath, and nosleep 3600process is left afterwards. The issue's run of the same setup onmainhung past 90 s with empty stdout.Risk
M. Every probe's spawn path changes. The budgets match the old per-site values, and the crawler probes only gain a bound.
Remaining (#845 later slices)
vendor/npm_dir.rs'sgit check-ignoreexchange (after Fix vendored npm-family tarballs dropped by .gitignore (#831) #837, which edits that file).CommandRunner.output()outsideutils::process"architecture_testsguard.🤖 Generated with Claude Code
https://claude.ai/code/session_01Mr9d6u7vNrWPgoibe1ZRXd
Generated by Claude Code