Skip to content

Commit

Permalink
Fix keepalive connections not being closed in time (#4956)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Svetlov <[email protected]>
  • Loading branch information
bitphage and asvetlov authored Oct 17, 2020
1 parent 3020edc commit 35b3174
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 1 deletion.
10 changes: 10 additions & 0 deletions CHANGES/3296.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Fix keepalive connections not being closed in time

Refactoring in 964921d4e97e7c84bcfda6772ed458549aea0b09 introduced a
regression so that `_cleanup()` could be called only once or few times.
`_release()` expects `self._cleanup_handle` to be None to add new
`weakref_handle`. But when `_cleanup()` called and there are no
remaining connections, `self._cleanup_handle` will remain as
`<TimerHandle cancelled when=5853434>`, so `_release()` will not have a
chance to schedule `_cleanup()` call again.

1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ Vincent Maillol
Vitalik Verhovodov
Vitaly Haritonsky
Vitaly Magerya
Vladimir Kamarzin
Vladimir Kozlovski
Vladimir Rutsky
Vladimir Shulyak
Expand Down
3 changes: 3 additions & 0 deletions aiohttp/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ def _cleanup(self) -> None:
"""Cleanup unused transports."""
if self._cleanup_handle:
self._cleanup_handle.cancel()
# _cleanup_handle should be unset, otherwise _release() will not
# recreate it ever!
self._cleanup_handle = None

now = self._loop.time()
timeout = self._keepalive_timeout
Expand Down
3 changes: 2 additions & 1 deletion tests/test_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ async def test_release(loop, key) -> None:

conn._release(key, proto)
assert conn._release_waiter.called
assert conn._cleanup_handle is not None
assert conn._conns[key][0][0] == proto
assert conn._conns[key][0][1] == pytest.approx(loop.time(), abs=0.1)
assert not conn._cleanup_closed_transports
Expand Down Expand Up @@ -1198,7 +1199,7 @@ async def test_cleanup(key) -> None:
conn._cleanup()
assert existing_handle.cancel.called
assert conn._conns == {}
assert conn._cleanup_handle is not None
assert conn._cleanup_handle is None


async def test_cleanup_close_ssl_transport(loop, ssl_key) -> None:
Expand Down

0 comments on commit 35b3174

Please sign in to comment.