Ensure mounted transports are closed even if main transport raises - #3769
Ensure mounted transports are closed even if main transport raises#3769bysiber wants to merge 1 commit into
Conversation
When closing a client with proxy mounts, if the main transport's close/exit raises an exception, the mounted transports would never be cleaned up. This could lead to leaked connections. Wrap the main transport cleanup in try/finally to ensure mounted transports are always properly closed.
| finally: | ||
| for transport in self._mounts.values(): | ||
| if transport is not None: | ||
| transport.close() |
There was a problem hiding this comment.
Cleanup still stops at the first mounted transport that raises, so later mounts remain open. On ff7190e, I used the public Client(transport=..., mounts=...) API with a main transport whose close() raises, a first mounted transport whose close() also raises, and a second mounted transport that records cleanup. client.close() produced calls=['main', 'first']; the second mount was never closed, and the first mount's exception replaced the original main-transport exception. The async loops have the same short-circuit behavior.
To meet this PR's all-transports cleanup goal, each mounted cleanup needs to be attempted independently while preserving or aggregating the raised exceptions.
Disclosure: I ran the changed client module through Bandit → SARIF → Lumi Trace at NOQT (which ranked _client.py first), then verified this with the focused runtime repro above.
When closing a client with proxy mounts, if the main transport's
close()/__exit__()raises an exception, the mounted proxy transports would never be cleaned up. This wraps transport cleanup intry/finallyto ensure all transports are properly closed.Affects
Client.close(),Client.__exit__(),AsyncClient.aclose(), andAsyncClient.__aexit__().