Repository navigation
Python: [Bug]: Background session release waits past its finite timeout during cancellation cleanup #9231
Description
Activity
- addedpythonUsage: [Issues, PRs], Target: PythonUsage: [Issues, PRs], Target: PythontriageUsage: [Issues], Target: All issues that still need to be triagedUsage: [Issues], Target: All issues that still need to be triaged
on Oct 9, 2026 - addedreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
on Oct 9, 2026 🤖 Automated triage reproduction notes (agent-authored — trust but verify)
Agent analysis
Repro:
python/packages/core/agent_framework/_harness/_background_agents.py::BackgroundAgentsProvider._drain_runtimeat lines 405-458 exceeds a finite timeout when a tracked task repeatedly catches cancellation during finite cleanup. The public trigger isrelease_session(session, timeout=0.03)after starting such a task throughbackground_agents_start_task. Minimal repro: run the added test, which defers cleanup for 0.35 seconds and observes release returning after approximately 0.351 seconds.- Failing test:
python/packages/core/tests/core/test_harness_background_agents.py::test_release_session_timeout_bounds_deferred_cancellation_cleanup - Files examined: python/AGENTS.md, python/.github/skills/python-testing/SKILL.md, python/packages/core/AGENTS.md, python/packages/core/pyproject.toml, python/packages/core/agent_framework/_harness/_background_agents.py, python/packages/core/tests/core/test_harness_background_agents.py
- Tests run: test_release_session_timeout_bounds_deferred_cancellation_cleanup, test_release_session_times_out_if_task_ignores_cancellation, test_release_session_cancels_and_clears, test_release_session_raises_if_cancel_running_false
- Reported version:
1.21.0 - Current version:
1.21.0
- Failing test:
- addedharness[Issues, PRs], Target: harness-level items[Issues, PRs], Target: harness-level itemsand removedtriageUsage: [Issues], Target: All issues that still need to be triagedUsage: [Issues], Target: All issues that still need to be triaged
on Oct 9, 2026 charan-rathore commented
on Oct 10, 2026 ContributorMore actionsI reproduced this on current main (fd52de7) with the issue's script:
release_session(session, timeout=0.03)blocked 0.351s against the deferred-cleanup client, while the cooperative-cancellation control returned promptly. Cross-checked on Linux against the Windows/Python 3.14 report - same behavior.One scoping note from tracing
_drain_runtime: the never-settling task case is already bounded - what escapes the deadline is specifically a task that catchesCancelledErrorand resumes a finite cleanup.wait_for(gather(...))cancels at the deadline and then waits for the gather to settle, and a cancel-swallowing task keeps that gather pending until its cleanup completes, so the timeout stops being a bound. A deadline-based abandon (e.g.asyncio.waitwith the remaining budget, then dropping and observing the stragglers under the existing abandonment policy) would keep the bound without changing the cooperative,timeout=None, orcancel_running=Falsepaths.I see this is assigned to westey (@westey-m) - if there's no internal fix already in flight, I'd be glad to open a PR along those lines. Happy to hold off if you'd rather take it internally.
Instinct assisted with the reproduction and analysis.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Observed Behavior
BackgroundAgentsProvider.release_session(session, timeout=0.03)waits for a background agent to finish deferred cancellation cleanup instead of returning at the configured timeout. A realAgent.runwith an offlineBaseChatClientthat finishes its cleanup after 0.35 seconds makes release take about 0.35–0.36 seconds. A cooperative cancellation control returns promptly with the same timeout.The deferred-cleanup client catches repeated
CancelledErrorwhile finishing a finite cleanup operation. The provider requests cancellation, reaches its timeout, then continues waiting for that task to settle. This extends the host's session teardown beyond its configured bound. The reproduction finishes on its own; it does not run a permanently hanging task.Expected Behavior
A finite release timeout should bound the provider's wait for cancellation, with unfinished tasks handled using the existing abandonment/exception-observation policy. Cooperative task cancellation,
timeout=None, and thecancel_running=Falseguard should retain their behavior.Steps to Reproduce
agent-framework-coresource.Agentand starts itsrunthrough the public background-task tool, first with cooperative cancellation and then with finite deferred cleanup.timeout=0.03; only the deferred-cleanup case waits until the 0.35-second cleanup finishes.Minimal Reproduction
Representative actual output on Windows/Python 3.14.3:
Error Messages and Stack Traces
No exception is raised by
release_session. After waiting for cleanup to finish, it logs:The experimental-provider and offline-client function-invocation warnings are retained; no model or network client is used.
Package Versions
Executed
agent-framework-coresource from current main2d9cc3f8ae465baf1aed3022f89b6848db4ffa7b(pyproject.tomlversion 1.21.0). All 84 core-package Python files match that commit. The existing environment has cachedagent-framework-core1.20.0 dependency metadata; this is a source-based reproduction, without a fresh workspace-lock install.Python Version
Python 3.14.3
Operating System
Windows
Regression
Unknown
Additional Context
The current
_drain_runtimewrapsasyncio.gather(*pending, return_exceptions=True)inasyncio.wait_for. Its timeout cancels the gather and then waits for cancellation to finish, so the catch/abandonment branch is not reached at the deadline when the background task defers cancellation cleanup.This follows the existing release contract introduced by PratikWayase in #7450, addressing antsok's #7385. moonbox3's review asked for a bounded shutdown policy; the accepted implementation added the timeout. The Foundry cleanup guidance in eavanvalkenburg's merged #8899 also relies on the finite provider bound. This report concerns the local release wait; the distributed runtime/lease work in #8760 and karthik-0306's #9040 remains separate.
Additional public controls exercised cooperative cancellation, finite deferred cleanup,
timeout=0,timeout=None, and rejecting a release withcancel_running=Falsewhile a task is running. Both a protocol-compatible offline agent and a realAgent.runreproduce the finite-timeout discrepancy. No full core suite, external model/service, other operating system, or performance validation was run. Please confirm the scoped direction of enforcing the existing finite release wait before implementation.AI Assistance
AI-assisted analysis, reproduction, and writing.
Acknowledgements