https://github.com/python/cpython/commit/461ca2cbfb7c92b80e14463854525f162716b8ff
commit: 461ca2cbfb7c92b80e14463854525f162716b8ff
branch: 3.11
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: ambv <luk...@langa.pl>
date: 2025-05-14T20:31:04+02:00
summary:

[3.11] gh-126500: test_ssl: Don't stop ThreadedEchoServer on OSError in 
ConnectionHandler; rely on __exit__ (GH-126503) (GH-126572) (GH-133148)

gh-126500: test_ssl: Don't stop ThreadedEchoServer on OSError in 
ConnectionHandler; rely on __exit__ (GH-126503)

If `read()` in the ConnectionHandler thread raises `OSError` (except 
`ConnectionError`),
the ConnectionHandler shuts down the entire ThreadedEchoServer,
preventing further connections.
It also does that for `EPROTOTYPE` in `wrap_conn`.

As far as I can see, this is done to avoid the server thread getting stuck,
forgotten, in its accept loop. However, since 2011 
(5b95eb90a7167285b6544b50865227c584943c9a)
the server is used as a context manager, and its `__exit__` does `stop()` and 
`join()`.
(I'm not sure if we *always* used `with` since that commit, but currently we 
do.)

Make sure that the context manager *is* used, and remove the `server.stop()`
calls from ConnectionHandler.

(cherry picked from commit c9cda1608edf7664c10f4f467e24591062c2fe62)
(cherry picked from commit aee80cd5e7c6be90c69b9aa9c09faa19b91cdccd)

Co-authored-by: Petr Viktorin <encu...@gmail.com>

files:
M Lib/test/test_ssl.py

diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 203351bd60e0c6..0b169c37d571b4 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -2516,7 +2516,6 @@ def wrap_conn(self):
                 # See also 
http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
                 if e.errno != errno.EPROTOTYPE and sys.platform != "darwin":
                     self.running = False
-                    self.server.stop()
                     self.close()
                 return False
             else:
@@ -2651,10 +2650,6 @@ def run(self):
                     self.close()
                     self.running = False
 
-                    # normally, we'd just stop here, but for the test
-                    # harness, we want to stop the server
-                    self.server.stop()
-
     def __init__(self, certificate=None, ssl_version=None,
                  certreqs=None, cacerts=None,
                  chatty=True, connectionchatty=False, starttls_server=False,
@@ -2688,21 +2683,33 @@ def __init__(self, certificate=None, ssl_version=None,
         self.conn_errors = []
         threading.Thread.__init__(self)
         self.daemon = True
+        self._in_context = False
 
     def __enter__(self):
+        if self._in_context:
+            raise ValueError('Re-entering ThreadedEchoServer context')
+        self._in_context = True
         self.start(threading.Event())
         self.flag.wait()
         return self
 
     def __exit__(self, *args):
+        assert self._in_context
+        self._in_context = False
         self.stop()
         self.join()
 
     def start(self, flag=None):
+        if not self._in_context:
+            raise ValueError(
+                'ThreadedEchoServer must be used as a context manager')
         self.flag = flag
         threading.Thread.start(self)
 
     def run(self):
+        if not self._in_context:
+            raise ValueError(
+                'ThreadedEchoServer must be used as a context manager')
         self.sock.settimeout(1.0)
         self.sock.listen(5)
         self.active = True

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to