Repository navigation
0.1.12: nagoya::process, and a local-reactor timer wake fix - #15
Merged
Merged
Conversation
added 3 commits
September 23, 2026 20:21
When the reactor fired a due timer itself inside poll_once, the waker saw it was inside the wait and skipped the syscall; the timer heap was then empty, so the reactor blocked in kevent with no timeout and nothing left to wake it. nagoya::timeout under block_on_with hung for good. A timer that woke a waker now makes that wait non-blocking. The regression test drives the race deterministically and fails in 5 s without the fix. 0.1.12.
agent-abstraction spawns the provider CLIs with tokio::process, which is the last thing holding tokio in agency-proxy. This is the same surface, spelled the way tokio spells it: Command, Child, and ChildStdin/Stdout/Stderr as futures-io AsyncWrite/AsyncRead, behind a `process` feature. Pipes are non-blocking and registered on one process-wide reactor that is never dropped, so the futures run under any executor. Exit is an event, not a poll: a per-child kqueue holding EVFILT_PROC/NOTE_EXIT on macOS and the BSDs, registered as readable on the reactor, and pidfd_open on Linux, with a waitid WNOWAIT thread only where pidfd is unavailable. wait is cancel safe, and a child dropped unreaped is reaped by the reactor rather than left a zombie.
nagoya::process started a process-wide reactor on first spawn and kept it in a OnceLock for the life of the process. That is hidden global state and a thread nobody asked for, created at whatever moment the first child happens to be spawned; nagoya refuses exactly that elsewhere, and an application that must register its signals before any thread exists (a Linux signalfd) could not guarantee it. spawn, output and status take the Handle to register on, as a socket in net does. The caller owns the Reactor and its lifetime, and every test starts its own. Also adds process_group, which agent-abstraction needs so that killing a run reaches the processes the agent started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Releases 0.1.12. Two changes:
nagoya::process(newprocessfeature):Command,Child, andChildStdin/ChildStdout/ChildStderr, spelled the way tokio spells them. The pipes are futures-ioAsyncWrite/AsyncRead. Pipes are non-blocking on one process-wide reactor that is never dropped, so the futures run under any executor. Exit is an event, not a poll: a per-child kqueue withEVFILT_PROC/NOTE_EXITon macOS and the BSDs (registered as readable on the reactor), andpidfd_openon Linux, with awaitid(WNOWAIT)thread only where pidfd is unavailable.waitis cancel safe, and a child dropped unreaped is reaped by the reactor instead of being left as a zombie. This is what lets agent-abstraction, and through it agency-proxy, drop tokio.feat/resolvebranch, carried here).nagoya::timeoutunderblock_on_withcould hang for good: a due timer fired insidepoll_oncewoke a waker that skipped its syscall, and the reactor then blocked with nothing left to wake it. Has its own regression test.Checked locally:
cargo test --features process --test process: 12 pass in 0.21s. Covers echo to EOF,catround trip,falseunder a foreign executor,output()of both streams, promptkill,kill_on_dropreaps, a droppedwaitcan be waited again, 16 children at once, write-after-close is an error, and a missing program isNotFound.cargo test --all-features: all 13 suites pass.cargo clippy --all-features --all-targets -D warningsandcargo fmt --checkare clean.The Linux pidfd path compiles only on Linux, so CI's Linux run is the first to build it.