diff --git a/Lib/test/support/threading_helper.py b/Lib/test/support/threading_helper.py index 0632577cdb..18c88cb594 100644 --- a/Lib/test/support/threading_helper.py +++ b/Lib/test/support/threading_helper.py @@ -183,12 +183,13 @@ class catch_threading_exception: # (to avoid reference cycles) """ - def __init__(self): + def __init__(self, cleanup=None): self.exc_type = None self.exc_value = None self.exc_traceback = None self.thread = None self._old_hook = None + self.cleanup = cleanup def _hook(self, args): self.exc_type = args.exc_type @@ -203,6 +204,8 @@ class catch_threading_exception: def __exit__(self, *exc_info): threading.excepthook = self._old_hook + if self.cleanup is not None: + self.cleanup(self.exc_type, self.exc_value, self.exc_traceback, self.thread) del self.exc_type del self.exc_value del self.exc_traceback diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index ecb6049a67..b6595bd11b 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -4430,7 +4430,12 @@ class TestPostHandshakeAuth(unittest.TestCase): # Ignore expected SSLError in ConnectionHandler of ThreadedEchoServer # (it is only raised sometimes on Windows) - with threading_helper.catch_threading_exception() as cm: + # If this is raised we will manually cleanup to avoid a + # ResourceWarning + def thread_cleanup(exc_type, exc_value, exc_traceback, thread): + if exc_type == ssl.SSLError: + thread.sslconn.close() + with threading_helper.catch_threading_exception(thread_cleanup) as cm: server = ThreadedEchoServer(context=server_context, chatty=False) with server: with client_context.wrap_socket(socket.socket(), @@ -4447,6 +4452,17 @@ class TestPostHandshakeAuth(unittest.TestCase): 'tlsv13 alert certificate required'): s.recv(1024) + # If ConnectionHandler did raise an SSLError manually + # close the connection to avoid a ResourceWarning + # Note: there is a race condition where + # the details of the exception in the thread may not be + # populated in cm before __exit__ + # is called. As a very naive approach add a sleep to avoid + # this + time.sleep(1) + if cm.exc_type == ssl.SSLError: + cm.thread.sslconn.close() + def test_pha_optional(self): if support.verbose: sys.stdout.write("\n")