Revert `resources.pop()` back inside `run_ctx` inner finally
Reverts the `_Cache.run_ctx` change frommaybe_open_ctx_locking93aa39dbwhich 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 orig93aa39dbrationale 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
parent
06cfe8999a
commit
007b45857b
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue