Repository navigation
fix(execution): reserve process capacity before launching - #1092
PierrunoYT wants to merge 1 commit into
Conversation
Reject starts when all slots are live or reserved, prune only completed history, and release reservations on launch failure. Keep live processes tracked even after failed termination. Add concurrent admission and real-process regressions for Twigpine#1085. Amp-Thread-ID: https://ampcode.com/threads/T-01a0dcd5-eb93-74c9-a1ac-5b140edaf973 Co-authored-by: Pierre Bruno <pierrebruno@hotmail.ch>
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: Gitlawb/zero/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review. WalkthroughProcessManager now reserves capacity before starting a process. When a positive limit is full, it prunes a completed process or returns ChangesProcess Capacity Enforcement
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant Start as ProcessManager.Start
participant ProcessManager
participant Transport
participant ChildProcess
Start->>ProcessManager: request process start
ProcessManager->>ProcessManager: reserve capacity
ProcessManager->>Transport: start process
Transport->>ChildProcess: launch OS process
Transport-->>ProcessManager: return launch result
ProcessManager->>ProcessManager: store process and release reservation
Suggested reviewers: Merge Risk: ⚪ Minimal · up to Process capacity is reserved before launch, and completed processes can free slots for later starts. No identified issue prevents merging after normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The new admission rule prevents launches from exceeding the configured limit and avoids evicting running processes. A stalled launch could occupy capacity without being reachable by the normal stop operation; whether this can occur in production remains uncertain. Retained concerns
Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Vasanthdev2004
left a comment
There was a problem hiding this comment.
Reviewed at 79ff80ed. Rejecting at capacity instead of evicting a live process is one of the options #1085 offered, and it makes the limit strict, so the eight-process floor I said could stay goes with the eviction. That's the right trade: a rejection tells the caller to stop something, where an eviction killed a process somebody may still have wanted.
The reservation holds on every path. Each start between reserve and store either stores the process or gives the slot back, and no wording about eviction is left for the model to read. Each piece is load-bearing:
- Dropping the capacity check fails
TestProcessManagerReservesCapacityBeforeTransportand both legs ofTestProcessManagerCapacityDoesNotEvictLiveProcesses. - Keeping the reservation after a failed launch fails with
failed launch did not release reservation. - Letting
Removeforget a live process frees a slot the capacity test then catches. - Keeping the reservation in
storestops the slot being reused after completion inTestProcessManagerCapacityWithRunningProcess.
internal/execution passes natively on Windows, and under -race for the manager tests. CI is 9 of 9 at head. Approving.
anandh8x
left a comment
There was a problem hiding this comment.
LGTM. Verified the reservation is taken before transport start and released on every path, and the new tests fail on main for the intended reasons.
euxaristia
left a comment
There was a problem hiding this comment.
The reserve-before-launch race is closed: the starting counter lives under the same mutex as the map, completed-only pruning means no live eviction, both failure paths release, and the test drives the race with a real blocked transport and a live process.
What changed
Fixes #1085 (approved for community implementation).
Reserve capacity under the manager lock before starting the transport. In-flight launches count toward
MaxProcesses; launch failures release their reservation and admission failures clean up prepared resources. At capacity, prune completed history only and returnErrProcessCapacityif every slot is live or reserved.This intentionally replaces live eviction with rejection, including for limits below eight. Admission no longer selects a live victim or treats a kill attempt as recovered capacity, eliminating the shared-victim race and the capacity consequences of ignored kill errors.
Stop/StopAllsignatures are unchanged.Removecannot forget a live process and bypass accounting. Zero still means the default limit (64), and negative limits remain unlimited.Regression evidence
Ran the new tests against the original implementation using a Go source overlay. They failed for the intended reasons:
Coverage includes 16 simultaneous starts behind a blocked transport, reservation release after transport failure, prepared-resource cleanup, failed termination, attempted removal of live identity, completed-history pruning, and a real child process at
MaxProcesses=1followed by slot reuse after completion. New tests use portable Go child processes/fake transports rather than POSIX shell commands.Verification
Executed on Linux amd64 with the Go version in
go.mod(1.26.6):make fmt-check— passedgo vet ./...— passedgo test ./...— passedgo test -race ./internal/execution -count=1— passedgo test -race ./internal/execution -run 'TestProcessManager(ReservesCapacity|CapacityDoes|CapacityWith)' -count=30— passedgo run ./cmd/zero-release build— passedgo run ./cmd/zero-release smoke—zero smoke check passed (0.9.0)make vulncheck—No vulnerabilities found.git diff HEAD --check— passed before commitmake lint-static— four pre-existing, unrelated advisory staticcheck findings: QF1001 ininternal/installtest/workflow_permissions_test.go:20; QF1008 ininternal/proxydial/proxydial.go:67,72andinternal/tools/web_fetch.go:315. No findings in changed files.Native macOS and Windows execution was not available in this Linux orb. Upstream
mainwas fetched and confirmed unchanged before committing.Summary by CodeRabbit