Skip to content

Commit 461ca2c

Browse files
[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 (5b95eb9) 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 c9cda16) (cherry picked from commit aee80cd) Co-authored-by: Petr Viktorin <[email protected]>
1 parent ab47462 commit 461ca2c

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

Lib/test/test_ssl.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -2516,7 +2516,6 @@ def wrap_conn(self):
25162516
# See also http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
25172517
if e.errno != errno.EPROTOTYPE and sys.platform != "darwin":
25182518
self.running = False
2519-
self.server.stop()
25202519
self.close()
25212520
return False
25222521
else:
@@ -2651,10 +2650,6 @@ def run(self):
26512650
self.close()
26522651
self.running = False
26532652

2654-
# normally, we'd just stop here, but for the test
2655-
# harness, we want to stop the server
2656-
self.server.stop()
2657-
26582653
def __init__(self, certificate=None, ssl_version=None,
26592654
certreqs=None, cacerts=None,
26602655
chatty=True, connectionchatty=False, starttls_server=False,
@@ -2688,21 +2683,33 @@ def __init__(self, certificate=None, ssl_version=None,
26882683
self.conn_errors = []
26892684
threading.Thread.__init__(self)
26902685
self.daemon = True
2686+
self._in_context = False
26912687

26922688
def __enter__(self):
2689+
if self._in_context:
2690+
raise ValueError('Re-entering ThreadedEchoServer context')
2691+
self._in_context = True
26932692
self.start(threading.Event())
26942693
self.flag.wait()
26952694
return self
26962695

26972696
def __exit__(self, *args):
2697+
assert self._in_context
2698+
self._in_context = False
26982699
self.stop()
26992700
self.join()
27002701

27012702
def start(self, flag=None):
2703+
if not self._in_context:
2704+
raise ValueError(
2705+
'ThreadedEchoServer must be used as a context manager')
27022706
self.flag = flag
27032707
threading.Thread.start(self)
27042708

27052709
def run(self):
2710+
if not self._in_context:
2711+
raise ValueError(
2712+
'ThreadedEchoServer must be used as a context manager')
27062713
self.sock.settimeout(1.0)
27072714
self.sock.listen(5)
27082715
self.active = True

0 commit comments

Comments
 (0)