@@ -4855,12 +4855,16 @@ class TestPreHandshakeClose(unittest.TestCase):
4855
4855
4856
4856
class SingleConnectionTestServerThread (threading .Thread ):
4857
4857
4858
- def __init__ (self , * , name , call_after_accept ):
4858
+ def __init__ (self , * , name , call_after_accept , timeout = None ):
4859
4859
self .call_after_accept = call_after_accept
4860
4860
self .received_data = b'' # set by .run()
4861
4861
self .wrap_error = None # set by .run()
4862
4862
self .listener = None # set by .start()
4863
4863
self .port = None # set by .start()
4864
+ if timeout is None :
4865
+ self .timeout = support .SHORT_TIMEOUT
4866
+ else :
4867
+ self .timeout = timeout
4864
4868
super ().__init__ (name = name )
4865
4869
4866
4870
def __enter__ (self ):
@@ -4883,13 +4887,19 @@ def start(self):
4883
4887
self .ssl_ctx .load_cert_chain (certfile = ONLYCERT , keyfile = ONLYKEY )
4884
4888
self .listener = socket .socket ()
4885
4889
self .port = socket_helper .bind_port (self .listener )
4886
- self .listener .settimeout (2.0 )
4890
+ self .listener .settimeout (self . timeout )
4887
4891
self .listener .listen (1 )
4888
4892
super ().start ()
4889
4893
4890
4894
def run (self ):
4891
- conn , address = self .listener .accept ()
4892
- self .listener .close ()
4895
+ try :
4896
+ conn , address = self .listener .accept ()
4897
+ except TimeoutError :
4898
+ # on timeout, just close the listener
4899
+ return
4900
+ finally :
4901
+ self .listener .close ()
4902
+
4893
4903
with conn :
4894
4904
if self .call_after_accept (conn ):
4895
4905
return
@@ -4917,8 +4927,13 @@ def non_linux_skip_if_other_okay_error(self, err):
4917
4927
# we're specifically trying to test. The way this test is written
4918
4928
# is known to work on Linux. We'll skip it anywhere else that it
4919
4929
# does not present as doing so.
4920
- self .skipTest (f"Could not recreate conditions on { sys .platform } :"
4921
- f" { err = } " )
4930
+ try :
4931
+ self .skipTest (f"Could not recreate conditions on { sys .platform } :"
4932
+ f" { err = } " )
4933
+ finally :
4934
+ # gh-108342: Explicitly break the reference cycle
4935
+ err = None
4936
+
4922
4937
# If maintaining this conditional winds up being a problem.
4923
4938
# just turn this into an unconditional skip anything but Linux.
4924
4939
# The important thing is that our CI has the logic covered.
@@ -4929,7 +4944,7 @@ def test_preauth_data_to_tls_server(self):
4929
4944
4930
4945
def call_after_accept (unused ):
4931
4946
server_accept_called .set ()
4932
- if not ready_for_server_wrap_socket .wait (2.0 ):
4947
+ if not ready_for_server_wrap_socket .wait (support . SHORT_TIMEOUT ):
4933
4948
raise RuntimeError ("wrap_socket event never set, test may fail." )
4934
4949
return False # Tell the server thread to continue.
4935
4950
@@ -4951,20 +4966,31 @@ def call_after_accept(unused):
4951
4966
4952
4967
ready_for_server_wrap_socket .set ()
4953
4968
server .join ()
4969
+
4954
4970
wrap_error = server .wrap_error
4955
- self .assertEqual (b"" , server .received_data )
4956
- self .assertIsInstance (wrap_error , OSError ) # All platforms.
4957
- self .non_linux_skip_if_other_okay_error (wrap_error )
4958
- self .assertIsInstance (wrap_error , ssl .SSLError )
4959
- self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
4960
- self .assertIn ("before TLS handshake with data" , wrap_error .reason )
4961
- self .assertNotEqual (0 , wrap_error .args [0 ])
4962
- self .assertIsNone (wrap_error .library , msg = "attr must exist" )
4971
+ server .wrap_error = None
4972
+ try :
4973
+ self .assertEqual (b"" , server .received_data )
4974
+ self .assertIsInstance (wrap_error , OSError ) # All platforms.
4975
+ self .non_linux_skip_if_other_okay_error (wrap_error )
4976
+ self .assertIsInstance (wrap_error , ssl .SSLError )
4977
+ self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
4978
+ self .assertIn ("before TLS handshake with data" , wrap_error .reason )
4979
+ self .assertNotEqual (0 , wrap_error .args [0 ])
4980
+ self .assertIsNone (wrap_error .library , msg = "attr must exist" )
4981
+ finally :
4982
+ # gh-108342: Explicitly break the reference cycle
4983
+ wrap_error = None
4984
+ server = None
4963
4985
4964
4986
def test_preauth_data_to_tls_client (self ):
4987
+ server_can_continue_with_wrap_socket = threading .Event ()
4965
4988
client_can_continue_with_wrap_socket = threading .Event ()
4966
4989
4967
4990
def call_after_accept (conn_to_client ):
4991
+ if not server_can_continue_with_wrap_socket .wait (support .SHORT_TIMEOUT ):
4992
+ print ("ERROR: test client took too long" )
4993
+
4968
4994
# This forces an immediate connection close via RST on .close().
4969
4995
set_socket_so_linger_on_with_zero_timeout (conn_to_client )
4970
4996
conn_to_client .send (
@@ -4986,8 +5012,10 @@ def call_after_accept(conn_to_client):
4986
5012
4987
5013
with socket .socket () as client :
4988
5014
client .connect (server .listener .getsockname ())
4989
- if not client_can_continue_with_wrap_socket .wait (2.0 ):
4990
- self .fail ("test server took too long." )
5015
+ server_can_continue_with_wrap_socket .set ()
5016
+
5017
+ if not client_can_continue_with_wrap_socket .wait (support .SHORT_TIMEOUT ):
5018
+ self .fail ("test server took too long" )
4991
5019
ssl_ctx = ssl .create_default_context ()
4992
5020
try :
4993
5021
tls_client = ssl_ctx .wrap_socket (
@@ -5001,24 +5029,31 @@ def call_after_accept(conn_to_client):
5001
5029
tls_client .close ()
5002
5030
5003
5031
server .join ()
5004
- self .assertEqual (b"" , received_data )
5005
- self .assertIsInstance (wrap_error , OSError ) # All platforms.
5006
- self .non_linux_skip_if_other_okay_error (wrap_error )
5007
- self .assertIsInstance (wrap_error , ssl .SSLError )
5008
- self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
5009
- self .assertIn ("before TLS handshake with data" , wrap_error .reason )
5010
- self .assertNotEqual (0 , wrap_error .args [0 ])
5011
- self .assertIsNone (wrap_error .library , msg = "attr must exist" )
5032
+ try :
5033
+ self .assertEqual (b"" , received_data )
5034
+ self .assertIsInstance (wrap_error , OSError ) # All platforms.
5035
+ self .non_linux_skip_if_other_okay_error (wrap_error )
5036
+ self .assertIsInstance (wrap_error , ssl .SSLError )
5037
+ self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
5038
+ self .assertIn ("before TLS handshake with data" , wrap_error .reason )
5039
+ self .assertNotEqual (0 , wrap_error .args [0 ])
5040
+ self .assertIsNone (wrap_error .library , msg = "attr must exist" )
5041
+ finally :
5042
+ # gh-108342: Explicitly break the reference cycle
5043
+ wrap_error = None
5044
+ server = None
5012
5045
5013
5046
def test_https_client_non_tls_response_ignored (self ):
5014
-
5015
5047
server_responding = threading .Event ()
5016
5048
5017
5049
class SynchronizedHTTPSConnection (http .client .HTTPSConnection ):
5018
5050
def connect (self ):
5051
+ # Call clear text HTTP connect(), not the encrypted HTTPS (TLS)
5052
+ # connect(): wrap_socket() is called manually below.
5019
5053
http .client .HTTPConnection .connect (self )
5054
+
5020
5055
# Wait for our fault injection server to have done its thing.
5021
- if not server_responding .wait (1.0 ) and support .verbose :
5056
+ if not server_responding .wait (support . SHORT_TIMEOUT ) and support .verbose :
5022
5057
sys .stdout .write ("server_responding event never set." )
5023
5058
self .sock = self ._context .wrap_socket (
5024
5059
self .sock , server_hostname = self .host )
@@ -5033,29 +5068,34 @@ def call_after_accept(conn_to_client):
5033
5068
server_responding .set ()
5034
5069
return True # Tell the server to stop.
5035
5070
5071
+ timeout = 2.0
5036
5072
server = self .SingleConnectionTestServerThread (
5037
5073
call_after_accept = call_after_accept ,
5038
- name = "non_tls_http_RST_responder" )
5074
+ name = "non_tls_http_RST_responder" ,
5075
+ timeout = timeout )
5039
5076
server .__enter__ () # starts it
5040
5077
self .addCleanup (server .__exit__ ) # ... & unittest.TestCase stops it.
5041
5078
# Redundant; call_after_accept sets SO_LINGER on the accepted conn.
5042
5079
set_socket_so_linger_on_with_zero_timeout (server .listener )
5043
5080
5044
5081
connection = SynchronizedHTTPSConnection (
5045
- f"localhost" ,
5082
+ server . listener . getsockname ()[ 0 ] ,
5046
5083
port = server .port ,
5047
5084
context = ssl .create_default_context (),
5048
- timeout = 2.0 ,
5085
+ timeout = timeout ,
5049
5086
)
5087
+
5050
5088
# There are lots of reasons this raises as desired, long before this
5051
5089
# test was added. Sending the request requires a successful TLS wrapped
5052
5090
# socket; that fails if the connection is broken. It may seem pointless
5053
5091
# to test this. It serves as an illustration of something that we never
5054
5092
# want to happen... properly not happening.
5055
- with self .assertRaises (OSError ) as err_ctx :
5093
+ with self .assertRaises (OSError ):
5056
5094
connection .request ("HEAD" , "/test" , headers = {"Host" : "localhost" })
5057
5095
response = connection .getresponse ()
5058
5096
5097
+ server .join ()
5098
+
5059
5099
5060
5100
def setUpModule ():
5061
5101
if support .verbose :
0 commit comments