Skip to content

fix(runtime): 共享子执行准入池,并在中断时释放已分配的槽位 - #828

Open
6iKUN6 wants to merge 5 commits into
openpi-dev:mainfrom
6iKUN6:fix/child-admission-shared-and-abort
Open

6iKUN6 wants to merge 5 commits into
openpi-dev:mainfrom
6iKUN6:fix/child-admission-shared-and-abort

Conversation

@6iKUN6

@6iKUN6 6iKUN6 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Pi evaluates each extension in its own module graph, so module-local admission registries let Workflow and Direct/BTW children exceed the configured Session child-execution limit. A cancellation arriving as a queued Direct spawn or restart acquired its permit could also leave that permit held indefinitely. Explicitly cancelling a restart in that window could still dispatch its backend send, and a second send while waiting could bypass admission entirely.

Value

The configured limit now bounds all child origins in one parent Session. Cancelling queued or starting Direct work no longer leaves later children blocked by an abandoned permit.

Approach

Share the existing Session-owner WeakMap through a versioned process-global symbol and replace a closed pool when Pi reloads the same SessionManager. Capture acquired permits in the promise continuation so cleanup owns them even when the Effect fiber is interrupted before resuming. Check cancellation before backend handoff, keep cleanup scoped to its own restart controller/lease without overriding a newer pending controller, and reject a second send while that restart is waiting for admission. Normal backend-active steering remains available.

Validation

Validated head: 17d767cbaea3d11a3ff3224564d60baafcf9f966, based on current main f98d6a4737461ba8d8ee100f113b5a7c3a0001a0. Original contributor history is preserved.

  • bun install --frozen-lockfile: passed; Pi SDK 1.2.0.

  • node --test --experimental-strip-types tests/extensions/shared/child-execution-admission.test.ts tests/extensions/subagents/manager.test.ts tests/extensions/subagents/pi-backend.test.ts tests/extensions/subagents/pi-backend-lifecycle.test.ts with isolated PI_CODING_AGENT_DIR: 68 passed, including the regression cases that failed before the restart repairs and backend-rejection recovery coverage.

  • Deterministic native SDK smoke: Pi's loader gives separately loaded extension fixtures the same pool; real child AgentSessions through the production Pi backend release permits after successful completion and cancellation of an active local faux-provider stream; actual AgentSession.reload() closes and recreates the pool for the same owner. Local Pi list reports this checkout as the single OpenPI source. No paid provider calls.

  • bun run check: passed (configuration/docs/discipline contracts, Web build, format, lint and typecheck).

  • bun run test: passed, 2,458 Node tests passed / 9 skipped / 0 failed; 1,338 UI tests passed in 88 files.

  • Interactive TUI and real-provider acceptance were not run.

  • Two independent final source reviews passed on this exact head. Current-head CI run 38694495923 passed all required checks, including Windows. Independent last-push approval remains required before merge.

Impact

  • User-visible behavior: the configured shared limit is enforced across Workflow, Direct and BTW; cancelling work no longer strands permits.
  • Model-visible context/tools: unchanged.
  • Runtime/lifecycle: process-shared, Session-scoped admission ownership; reload creates a fresh pool; abandoned asynchronous acquisitions release their own leases.
  • Persisted config/data: unchanged.
  • Compatibility/risk: no new dependency or tool surface; rollback is a source revert. Native smoke used the pinned Pi 1.2.0 SDK; minimum-host validation remains CI's responsibility.

…elease abandoned leases

Pi loads every extension with `moduleCache: false`, so Workflows and
Subagents each had their own module-level admission WeakMap and the
Session child execution limit was never shared. Keep the Session map on a
versioned `Symbol.for` global, and start a fresh pool when a reload finds
the previous one shut down.

A Direct spawn or restart interrupted after admission granted its slot,
but before the fiber resumed, dropped the lease and held the permit
forever. Take the lease from the promise continuation and release it
there once the caller's finalizer has run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the area:subagents Subagent delegation, skills, or tests label Oct 14, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:subagents Subagent delegation, skills, or tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants