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
2 people authored and asvetlov committed Oct 17, 2020
1 parent 3419080 commit 5b42104
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 @@ -274,6 +274,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 @@ -329,6 +329,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 @@ -390,6 +390,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 @@ -1215,7 +1216,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(ssl_key) -> None:
Expand Down

0 comments on commit 5b42104

Please sign in to comment.