diff options
author | Yury Selivanov <yury@magic.io> | 2017-06-10 14:01:17 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-10 14:01:17 (GMT) |
commit | 1395c58ef7b98f087d1d5d50962fe7a8c032f34d (patch) | |
tree | 9d746f53f9bf7b7046dca3048a14d6c3aec5dba4 /Lib/asyncio | |
parent | 1f73023b908b1d13ca31d162ba613e0186218be5 (diff) | |
download | cpython-1395c58ef7b98f087d1d5d50962fe7a8c032f34d.zip cpython-1395c58ef7b98f087d1d5d50962fe7a8c032f34d.tar.gz cpython-1395c58ef7b98f087d1d5d50962fe7a8c032f34d.tar.bz2 |
[3.5] bpo-29406: asyncio SSL contexts leak sockets after calling close with certain servers (GH-409) (#2063)
* bpo-29406: asyncio SSL contexts leak sockets after calling close with certain servers (#409)
(cherry picked from commit a608d2d5a7f1aabe9bcbfc220135c5e126189390)
* [3.5] bpo-29406: asyncio SSL contexts leak sockets after calling close with certain servers (GH-409)
* asyncio SSL contexts leak sockets after calling close with certain servers
* cleanup _shutdown_timeout_handle on _fatal_error.
(cherry picked from commit a608d2d5a7f1aabe9bcbfc220135c5e126189390)
Diffstat (limited to 'Lib/asyncio')
-rw-r--r-- | Lib/asyncio/sslproto.py | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 61d478e..4606f0b 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -7,6 +7,7 @@ except ImportError: # pragma: no cover from . import base_events from . import compat +from . import futures from . import protocols from . import transports from .log import logger @@ -411,7 +412,7 @@ class SSLProtocol(protocols.Protocol): def __init__(self, loop, app_protocol, sslcontext, waiter, server_side=False, server_hostname=None, - call_connection_made=True): + call_connection_made=True, shutdown_timeout=5.0): if ssl is None: raise RuntimeError('stdlib ssl module not available') @@ -442,6 +443,8 @@ class SSLProtocol(protocols.Protocol): self._session_established = False self._in_handshake = False self._in_shutdown = False + self._shutdown_timeout = shutdown_timeout + self._shutdown_timeout_handle = None # transport, ex: SelectorSocketTransport self._transport = None self._call_connection_made = call_connection_made @@ -556,6 +559,15 @@ class SSLProtocol(protocols.Protocol): self._in_shutdown = True self._write_appdata(b'') + if self._shutdown_timeout is not None: + self._shutdown_timeout_handle = self._loop.call_later( + self._shutdown_timeout, self._on_shutdown_timeout) + + def _on_shutdown_timeout(self): + if self._transport is not None: + self._fatal_error( + futures.TimeoutError(), 'Can not complete shitdown operation') + def _write_appdata(self, data): self._write_backlog.append((data, 0)) self._write_buffer_size += len(data) @@ -683,12 +695,22 @@ class SSLProtocol(protocols.Protocol): }) if self._transport: self._transport._force_close(exc) + self._transport = None + + if self._shutdown_timeout_handle is not None: + self._shutdown_timeout_handle.cancel() + self._shutdown_timeout_handle = None def _finalize(self): self._sslpipe = None if self._transport is not None: self._transport.close() + self._transport = None + + if self._shutdown_timeout_handle is not None: + self._shutdown_timeout_handle.cancel() + self._shutdown_timeout_handle = None def _abort(self): try: |