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,
|
||||
|
||||
) -> None:
|
||||
try:
|
||||
async with mng as value:
|
||||
_, no_more_users = cls.resources[ctx_key]
|
||||
try:
|
||||
cls.values[ctx_key] = value
|
||||
task_status.started(value)
|
||||
await no_more_users.wait()
|
||||
finally:
|
||||
value = cls.values.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'
|
||||
)
|
||||
async with mng as value:
|
||||
_, no_more_users = cls.resources[ctx_key]
|
||||
cls.values[ctx_key] = value
|
||||
task_status.started(value)
|
||||
try:
|
||||
await no_more_users.wait()
|
||||
finally:
|
||||
value = cls.values.pop(ctx_key)
|
||||
cls.resources.pop(ctx_key)
|
||||
|
||||
|
||||
class _UnresolvedCtx:
|
||||
|
|
|
|||
Loading…
Reference in New Issue