From 16ec20f8e0c098d8d114085fddfc567f1b56a8dc Mon Sep 17 00:00:00 2001 From: Kadir Can Ozden <101993364+bysiber@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:27:11 +0300 Subject: [PATCH] Fix CapacityLimiter._pending_borrowers leak on non-Cancelled exceptions acquire_on_behalf_of only catches trio.Cancelled when cleaning up _pending_borrowers. If park() raises any other exception (e.g. KeyboardInterrupt delivered via the abort mechanism), the task's entry remains in _pending_borrowers permanently. This is a slow memory leak and can also cause _wake_waiters to encounter stale entries. Broaden the handler to BaseException and use pop with a default to be safe against double-removal. --- src/trio/_sync.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/trio/_sync.py b/src/trio/_sync.py index dbdee0798..d8c16f6d9 100644 --- a/src/trio/_sync.py +++ b/src/trio/_sync.py @@ -377,8 +377,8 @@ async def acquire_on_behalf_of(self, borrower: Task | object) -> None: self._pending_borrowers[task] = borrower try: await self._lot.park() - except trio.Cancelled: - self._pending_borrowers.pop(task) + except BaseException: + self._pending_borrowers.pop(task, None) raise else: await trio.lowlevel.cancel_shielded_checkpoint()