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