bpo-29406: asyncio SSL contexts leak sockets after calling close with… · python/cpython@a608d2d (original) (raw)
`@@ -6,6 +6,8 @@
`
6
6
`ssl = None
`
7
7
``
8
8
`from . import base_events
`
``
9
`+
from . import compat
`
``
10
`+
from . import futures
`
9
11
`from . import protocols
`
10
12
`from . import transports
`
11
13
`from .log import logger
`
`@@ -407,7 +409,7 @@ class SSLProtocol(protocols.Protocol):
`
407
409
``
408
410
`def init(self, loop, app_protocol, sslcontext, waiter,
`
409
411
`server_side=False, server_hostname=None,
`
410
``
`-
call_connection_made=True):
`
``
412
`+
call_connection_made=True, shutdown_timeout=5.0):
`
411
413
`if ssl is None:
`
412
414
`raise RuntimeError('stdlib ssl module not available')
`
413
415
``
`@@ -438,6 +440,8 @@ def init(self, loop, app_protocol, sslcontext, waiter,
`
438
440
`self._session_established = False
`
439
441
`self._in_handshake = False
`
440
442
`self._in_shutdown = False
`
``
443
`+
self._shutdown_timeout = shutdown_timeout
`
``
444
`+
self._shutdown_timeout_handle = None
`
441
445
`# transport, ex: SelectorSocketTransport
`
442
446
`self._transport = None
`
443
447
`self._call_connection_made = call_connection_made
`
`@@ -552,6 +556,15 @@ def _start_shutdown(self):
`
552
556
`self._in_shutdown = True
`
553
557
`self._write_appdata(b'')
`
554
558
``
``
559
`+
if self._shutdown_timeout is not None:
`
``
560
`+
self._shutdown_timeout_handle = self._loop.call_later(
`
``
561
`+
self._shutdown_timeout, self._on_shutdown_timeout)
`
``
562
+
``
563
`+
def _on_shutdown_timeout(self):
`
``
564
`+
if self._transport is not None:
`
``
565
`+
self._fatal_error(
`
``
566
`+
futures.TimeoutError(), 'Can not complete shitdown operation')
`
``
567
+
555
568
`def _write_appdata(self, data):
`
556
569
`self._write_backlog.append((data, 0))
`
557
570
`self._write_buffer_size += len(data)
`
`@@ -679,12 +692,22 @@ def _fatal_error(self, exc, message='Fatal error on transport'):
`
679
692
` })
`
680
693
`if self._transport:
`
681
694
`self._transport._force_close(exc)
`
``
695
`+
self._transport = None
`
``
696
+
``
697
`+
if self._shutdown_timeout_handle is not None:
`
``
698
`+
self._shutdown_timeout_handle.cancel()
`
``
699
`+
self._shutdown_timeout_handle = None
`
682
700
``
683
701
`def _finalize(self):
`
684
702
`self._sslpipe = None
`
685
703
``
686
704
`if self._transport is not None:
`
687
705
`self._transport.close()
`
``
706
`+
self._transport = None
`
``
707
+
``
708
`+
if self._shutdown_timeout_handle is not None:
`
``
709
`+
self._shutdown_timeout_handle.cancel()
`
``
710
`+
self._shutdown_timeout_handle = None
`
688
711
``
689
712
`def _abort(self):
`
690
713
`try:
`