Gateway launch-failure leaves SESSION_WRITEBACK_OWNERS entry (follow-up from #6636)
#6,869 创建于 2026年8月9日
仓库指标
- 星标
- (17,224 个星标)
- PR 合并指标
- (平均合并 14小时 31分钟) (30 天内合并 314 个 PR)
描述
Follow-up from #6636 (shipped in exp-v0.52.187).
#6636 fixed the cancel-finalizer stale-write race and cleared the SESSION_WRITEBACK_OWNERS entry on the two Gateway paths that fire in normal use (final teardown + pre-start cancellation). A Codex re-gate identified one remaining leak site of the same class on the rare launch-failure path:
Where: api/routes.py — the writeback owner is registered in _prepare_chat_start_session_for_stream (register_session_writeback_owner(s.session_id, stream_id), ~line 21237) and again the launch continues through _start_chat_stream_for_session. If the launch ABORTS after registration — a s.save() throw in _prepare_..., a setup failure, or a Thread.start() throw at the try/except around thr.start() (~line 21579) — the owner entry is left populated indefinitely (one leaked entry per failed launch, process-lifetime).
Exact fix (per the Codex re-gate): enclose the interval from writeback-owner registration through successful worker start in launch-abort cleanup, calling clear_session_writeback_owner_if_owned(s.session_id, stream_id) on every abort path (save/setup/thread-start failure) before re-raising. The thr.start() except block (routes.py ~21582) already cleans up Gateway lifecycle state (_finish/_clear_gateway_run_starting) — add the writeback clear there, and cover the s.save()/setup failure interval too.
clear_session_writeback_owner_if_owned (api/config.py:8917) is compare-and-clear (only clears if stream_id still owns the entry), so it is safe to call on any abort path.
Severity: SILENT, low-frequency (only on launch failure), unbounded process-lifetime growth. Not a data-integrity issue (the core stale-write race is already fixed).
Add a revert-sensitive regression that forces a launch failure after registration and asserts the owner is cleared.