Revert `resources.pop()` back inside `run_ctx` inner finally

Reverts the `_Cache.run_ctx` change from 93aa39db which
moved `resources.pop(ctx_key)` to an outer `finally`
*after* the acm's `__aexit__()`. That introduced an
atomicity gap: `values` was already popped in the inner
finally but `resources` survived through the acm teardown
checkpoints. A re-entering task that creates a fresh lock
(the old one having been popped by the exiting caller)
could then acquire immediately and find stale `resources`
(for which now we raise a `RuntimeError('Caching resources ALREADY
exist?!')`).

Deats,
- the orig 93aa39db rationale was a preemptive guard
  against acm `__aexit__()` code accessing `_Cache`
  mid-teardown, but no `@acm` in `tractor` (or `piker`) ever
  does that; the scenario never materialized.
- by popping both `values` AND `resources` atomically
  (no checkpoint between them) in the inner finally,
  the re-entry race window is closed: either the new
  task sees both entries (cache hit) or neither
  (clean cache miss).
- `test_moc_reentry_during_teardown` now passes
  without `xfail`! (:party:)

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
maybe_open_ctx_locking
Gud Boi 2026-04-07 00:47:53 -04:00
parent 06cfe8999a
commit 007b45857b
1 changed files with 9 additions and 16 deletions

View File

@ -227,22 +227,15 @@ class _Cache:
task_status: trio.TaskStatus[T] = trio.TASK_STATUS_IGNORED, task_status: trio.TaskStatus[T] = trio.TASK_STATUS_IGNORED,
) -> None: ) -> None:
try: async with mng as value:
async with mng as value: _, no_more_users = cls.resources[ctx_key]
_, no_more_users = cls.resources[ctx_key] cls.values[ctx_key] = value
try: task_status.started(value)
cls.values[ctx_key] = value try:
task_status.started(value) await no_more_users.wait()
await no_more_users.wait() finally:
finally: value = cls.values.pop(ctx_key)
value = cls.values.pop(ctx_key) cls.resources.pop(ctx_key)
finally:
# discard nursery ref so it won't be re-used (an error)?
_rsrcs = cls.resources.pop(ctx_key)
log.error(
f'Popping ctx resources\n'
f'{_rsrcs}\n'
)
class _UnresolvedCtx: class _UnresolvedCtx: