@@ -4672,12 +4672,16 @@ class TestPreHandshakeClose(unittest.TestCase):
4672
4672
4673
4673
class SingleConnectionTestServerThread (threading .Thread ):
4674
4674
4675
- def __init__ (self , * , name , call_after_accept ):
4675
+ def __init__ (self , * , name , call_after_accept , timeout = None ):
4676
4676
self .call_after_accept = call_after_accept
4677
4677
self .received_data = b'' # set by .run()
4678
4678
self .wrap_error = None # set by .run()
4679
4679
self .listener = None # set by .start()
4680
4680
self .port = None # set by .start()
4681
+ if timeout is None :
4682
+ self .timeout = support .SHORT_TIMEOUT
4683
+ else :
4684
+ self .timeout = timeout
4681
4685
super ().__init__ (name = name )
4682
4686
4683
4687
def __enter__ (self ):
@@ -4700,13 +4704,19 @@ def start(self):
4700
4704
self .ssl_ctx .load_cert_chain (certfile = ONLYCERT , keyfile = ONLYKEY )
4701
4705
self .listener = socket .socket ()
4702
4706
self .port = socket_helper .bind_port (self .listener )
4703
- self .listener .settimeout (2.0 )
4707
+ self .listener .settimeout (self . timeout )
4704
4708
self .listener .listen (1 )
4705
4709
super ().start ()
4706
4710
4707
4711
def run (self ):
4708
- conn , address = self .listener .accept ()
4709
- self .listener .close ()
4712
+ try :
4713
+ conn , address = self .listener .accept ()
4714
+ except TimeoutError :
4715
+ # on timeout, just close the listener
4716
+ return
4717
+ finally :
4718
+ self .listener .close ()
4719
+
4710
4720
with conn :
4711
4721
if self .call_after_accept (conn ):
4712
4722
return
@@ -4734,8 +4744,13 @@ def non_linux_skip_if_other_okay_error(self, err):
4734
4744
# we're specifically trying to test. The way this test is written
4735
4745
# is known to work on Linux. We'll skip it anywhere else that it
4736
4746
# does not present as doing so.
4737
- self .skipTest (f"Could not recreate conditions on { sys .platform } :"
4738
- f" { err = } " )
4747
+ try :
4748
+ self .skipTest (f"Could not recreate conditions on { sys .platform } :"
4749
+ f" { err = } " )
4750
+ finally :
4751
+ # gh-108342: Explicitly break the reference cycle
4752
+ err = None
4753
+
4739
4754
# If maintaining this conditional winds up being a problem.
4740
4755
# just turn this into an unconditional skip anything but Linux.
4741
4756
# The important thing is that our CI has the logic covered.
@@ -4746,7 +4761,7 @@ def test_preauth_data_to_tls_server(self):
4746
4761
4747
4762
def call_after_accept (unused ):
4748
4763
server_accept_called .set ()
4749
- if not ready_for_server_wrap_socket .wait (2.0 ):
4764
+ if not ready_for_server_wrap_socket .wait (support . SHORT_TIMEOUT ):
4750
4765
raise RuntimeError ("wrap_socket event never set, test may fail." )
4751
4766
return False # Tell the server thread to continue.
4752
4767
@@ -4767,20 +4782,31 @@ def call_after_accept(unused):
4767
4782
4768
4783
ready_for_server_wrap_socket .set ()
4769
4784
server .join ()
4785
+
4770
4786
wrap_error = server .wrap_error
4771
- self .assertEqual (b"" , server .received_data )
4772
- self .assertIsInstance (wrap_error , OSError ) # All platforms.
4773
- self .non_linux_skip_if_other_okay_error (wrap_error )
4774
- self .assertIsInstance (wrap_error , ssl .SSLError )
4775
- self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
4776
- self .assertIn ("before TLS handshake with data" , wrap_error .reason )
4777
- self .assertNotEqual (0 , wrap_error .args [0 ])
4778
- self .assertIsNone (wrap_error .library , msg = "attr must exist" )
4787
+ server .wrap_error = None
4788
+ try :
4789
+ self .assertEqual (b"" , server .received_data )
4790
+ self .assertIsInstance (wrap_error , OSError ) # All platforms.
4791
+ self .non_linux_skip_if_other_okay_error (wrap_error )
4792
+ self .assertIsInstance (wrap_error , ssl .SSLError )
4793
+ self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
4794
+ self .assertIn ("before TLS handshake with data" , wrap_error .reason )
4795
+ self .assertNotEqual (0 , wrap_error .args [0 ])
4796
+ self .assertIsNone (wrap_error .library , msg = "attr must exist" )
4797
+ finally :
4798
+ # gh-108342: Explicitly break the reference cycle
4799
+ wrap_error = None
4800
+ server = None
4779
4801
4780
4802
def test_preauth_data_to_tls_client (self ):
4803
+ server_can_continue_with_wrap_socket = threading .Event ()
4781
4804
client_can_continue_with_wrap_socket = threading .Event ()
4782
4805
4783
4806
def call_after_accept (conn_to_client ):
4807
+ if not server_can_continue_with_wrap_socket .wait (support .SHORT_TIMEOUT ):
4808
+ print ("ERROR: test client took too long" )
4809
+
4784
4810
# This forces an immediate connection close via RST on .close().
4785
4811
set_socket_so_linger_on_with_zero_timeout (conn_to_client )
4786
4812
conn_to_client .send (
@@ -4800,8 +4826,10 @@ def call_after_accept(conn_to_client):
4800
4826
4801
4827
with socket .socket () as client :
4802
4828
client .connect (server .listener .getsockname ())
4803
- if not client_can_continue_with_wrap_socket .wait (2.0 ):
4804
- self .fail ("test server took too long." )
4829
+ server_can_continue_with_wrap_socket .set ()
4830
+
4831
+ if not client_can_continue_with_wrap_socket .wait (support .SHORT_TIMEOUT ):
4832
+ self .fail ("test server took too long" )
4805
4833
ssl_ctx = ssl .create_default_context ()
4806
4834
try :
4807
4835
tls_client = ssl_ctx .wrap_socket (
@@ -4815,24 +4843,31 @@ def call_after_accept(conn_to_client):
4815
4843
tls_client .close ()
4816
4844
4817
4845
server .join ()
4818
- self .assertEqual (b"" , received_data )
4819
- self .assertIsInstance (wrap_error , OSError ) # All platforms.
4820
- self .non_linux_skip_if_other_okay_error (wrap_error )
4821
- self .assertIsInstance (wrap_error , ssl .SSLError )
4822
- self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
4823
- self .assertIn ("before TLS handshake with data" , wrap_error .reason )
4824
- self .assertNotEqual (0 , wrap_error .args [0 ])
4825
- self .assertIsNone (wrap_error .library , msg = "attr must exist" )
4846
+ try :
4847
+ self .assertEqual (b"" , received_data )
4848
+ self .assertIsInstance (wrap_error , OSError ) # All platforms.
4849
+ self .non_linux_skip_if_other_okay_error (wrap_error )
4850
+ self .assertIsInstance (wrap_error , ssl .SSLError )
4851
+ self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
4852
+ self .assertIn ("before TLS handshake with data" , wrap_error .reason )
4853
+ self .assertNotEqual (0 , wrap_error .args [0 ])
4854
+ self .assertIsNone (wrap_error .library , msg = "attr must exist" )
4855
+ finally :
4856
+ # gh-108342: Explicitly break the reference cycle
4857
+ wrap_error = None
4858
+ server = None
4826
4859
4827
4860
def test_https_client_non_tls_response_ignored (self ):
4828
-
4829
4861
server_responding = threading .Event ()
4830
4862
4831
4863
class SynchronizedHTTPSConnection (http .client .HTTPSConnection ):
4832
4864
def connect (self ):
4865
+ # Call clear text HTTP connect(), not the encrypted HTTPS (TLS)
4866
+ # connect(): wrap_socket() is called manually below.
4833
4867
http .client .HTTPConnection .connect (self )
4868
+
4834
4869
# Wait for our fault injection server to have done its thing.
4835
- if not server_responding .wait (1.0 ) and support .verbose :
4870
+ if not server_responding .wait (support . SHORT_TIMEOUT ) and support .verbose :
4836
4871
sys .stdout .write ("server_responding event never set." )
4837
4872
self .sock = self ._context .wrap_socket (
4838
4873
self .sock , server_hostname = self .host )
@@ -4847,28 +4882,33 @@ def call_after_accept(conn_to_client):
4847
4882
server_responding .set ()
4848
4883
return True # Tell the server to stop.
4849
4884
4885
+ timeout = 2.0
4850
4886
server = self .SingleConnectionTestServerThread (
4851
4887
call_after_accept = call_after_accept ,
4852
- name = "non_tls_http_RST_responder" )
4888
+ name = "non_tls_http_RST_responder" ,
4889
+ timeout = timeout )
4853
4890
self .enterContext (server ) # starts it & unittest.TestCase stops it.
4854
4891
# Redundant; call_after_accept sets SO_LINGER on the accepted conn.
4855
4892
set_socket_so_linger_on_with_zero_timeout (server .listener )
4856
4893
4857
4894
connection = SynchronizedHTTPSConnection (
4858
- f"localhost" ,
4895
+ server . listener . getsockname ()[ 0 ] ,
4859
4896
port = server .port ,
4860
4897
context = ssl .create_default_context (),
4861
- timeout = 2.0 ,
4898
+ timeout = timeout ,
4862
4899
)
4900
+
4863
4901
# There are lots of reasons this raises as desired, long before this
4864
4902
# test was added. Sending the request requires a successful TLS wrapped
4865
4903
# socket; that fails if the connection is broken. It may seem pointless
4866
4904
# to test this. It serves as an illustration of something that we never
4867
4905
# want to happen... properly not happening.
4868
- with self .assertRaises (OSError ) as err_ctx :
4906
+ with self .assertRaises (OSError ):
4869
4907
connection .request ("HEAD" , "/test" , headers = {"Host" : "localhost" })
4870
4908
response = connection .getresponse ()
4871
4909
4910
+ server .join ()
4911
+
4872
4912
4873
4913
class TestEnumerations (unittest .TestCase ):
4874
4914
0 commit comments