hataa 567a06783c
fix(mcp): tear down the in-flight owner when get_session is cancelled mid-eviction (#5008)
* fix(mcp): keep session owner teardown safe across cancellation paths

* fix(mcp): gate pooled-session publication on the commit inside the owner task

The owner resolved `ready` as soon as initialize() finished, but the
session only became pool property when the creator promoted it into
_entries in Phase 4. A concurrent get_session() could join the in-flight
creation and receive that session from Phase 2b while the creator was
still parked in the Phase-2 eviction teardown; cancelling the creator
then ran the Phase-2 unwind, which unconditionally shut the owner down —
closing the session underneath the joiner (#5008 review).

Move the commit into the owner task: initialize() success now pops the
in-flight record, registers the session in _entries, and resolves ready
with the session in one atomic critical section, so 'ready resolved with
a result' is exactly 'session registered and pool-owned'. Joiners can
therefore only ever receive a committed session, and both creator unwind
paths (Phase 2 and Phase 3) skip teardown when the creation already
committed, leaving the pooled session to LRU eviction / close_*. When the
record was removed before the commit (close_* or creator unwind), the
owner aborts and ready carries the same cancellation the old Phase-4
not-still-ours path raised, so joiners fail with the creation's outcome
instead of hanging or holding an unmanaged session.

test_cancelled_creator_does_not_close_session_held_by_joiner reproduces
the review's scenario deterministically (MAX_SESSIONS=1, hung LRU victim,
gated initialize, second caller receives the session, creator cancelled):
red on the previous commit, green now.
test_joiner_follows_creation_outcome_when_creator_is_cancelled pins the
joiner outcome-gating semantics as a drift guard.
2026-08-30 11:36:26 +08:00
..