@@ -4909,12 +4909,16 @@ class TestPreHandshakeClose(unittest.TestCase):
4909
4909
4910
4910
class SingleConnectionTestServerThread (threading .Thread ):
4911
4911
4912
- def __init__ (self , * , name , call_after_accept ):
4912
+ def __init__ (self , * , name , call_after_accept , timeout = None ):
4913
4913
self .call_after_accept = call_after_accept
4914
4914
self .received_data = b'' # set by .run()
4915
4915
self .wrap_error = None # set by .run()
4916
4916
self .listener = None # set by .start()
4917
4917
self .port = None # set by .start()
4918
+ if timeout is None :
4919
+ self .timeout = support .SHORT_TIMEOUT
4920
+ else :
4921
+ self .timeout = timeout
4918
4922
super ().__init__ (name = name )
4919
4923
4920
4924
def __enter__ (self ):
@@ -4937,13 +4941,19 @@ def start(self):
4937
4941
self .ssl_ctx .load_cert_chain (certfile = ONLYCERT , keyfile = ONLYKEY )
4938
4942
self .listener = socket .socket ()
4939
4943
self .port = socket_helper .bind_port (self .listener )
4940
- self .listener .settimeout (2.0 )
4944
+ self .listener .settimeout (self . timeout )
4941
4945
self .listener .listen (1 )
4942
4946
super ().start ()
4943
4947
4944
4948
def run (self ):
4945
- conn , address = self .listener .accept ()
4946
- self .listener .close ()
4949
+ try :
4950
+ conn , address = self .listener .accept ()
4951
+ except TimeoutError :
4952
+ # on timeout, just close the listener
4953
+ return
4954
+ finally :
4955
+ self .listener .close ()
4956
+
4947
4957
with conn :
4948
4958
if self .call_after_accept (conn ):
4949
4959
return
@@ -4971,8 +4981,13 @@ def non_linux_skip_if_other_okay_error(self, err):
4971
4981
# we're specifically trying to test. The way this test is written
4972
4982
# is known to work on Linux. We'll skip it anywhere else that it
4973
4983
# does not present as doing so.
4974
- self .skipTest (f"Could not recreate conditions on { sys .platform } :"
4975
- f" { err = } " )
4984
+ try :
4985
+ self .skipTest (f"Could not recreate conditions on { sys .platform } :"
4986
+ f" { err = } " )
4987
+ finally :
4988
+ # gh-108342: Explicitly break the reference cycle
4989
+ err = None
4990
+
4976
4991
# If maintaining this conditional winds up being a problem.
4977
4992
# just turn this into an unconditional skip anything but Linux.
4978
4993
# The important thing is that our CI has the logic covered.
@@ -4983,7 +4998,7 @@ def test_preauth_data_to_tls_server(self):
4983
4998
4984
4999
def call_after_accept (unused ):
4985
5000
server_accept_called .set ()
4986
- if not ready_for_server_wrap_socket .wait (2.0 ):
5001
+ if not ready_for_server_wrap_socket .wait (support . SHORT_TIMEOUT ):
4987
5002
raise RuntimeError ("wrap_socket event never set, test may fail." )
4988
5003
return False # Tell the server thread to continue.
4989
5004
@@ -5004,20 +5019,31 @@ def call_after_accept(unused):
5004
5019
5005
5020
ready_for_server_wrap_socket .set ()
5006
5021
server .join ()
5022
+
5007
5023
wrap_error = server .wrap_error
5008
- self .assertEqual (b"" , server .received_data )
5009
- self .assertIsInstance (wrap_error , OSError ) # All platforms.
5010
- self .non_linux_skip_if_other_okay_error (wrap_error )
5011
- self .assertIsInstance (wrap_error , ssl .SSLError )
5012
- self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
5013
- self .assertIn ("before TLS handshake with data" , wrap_error .reason )
5014
- self .assertNotEqual (0 , wrap_error .args [0 ])
5015
- self .assertIsNone (wrap_error .library , msg = "attr must exist" )
5024
+ server .wrap_error = None
5025
+ try :
5026
+ self .assertEqual (b"" , server .received_data )
5027
+ self .assertIsInstance (wrap_error , OSError ) # All platforms.
5028
+ self .non_linux_skip_if_other_okay_error (wrap_error )
5029
+ self .assertIsInstance (wrap_error , ssl .SSLError )
5030
+ self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
5031
+ self .assertIn ("before TLS handshake with data" , wrap_error .reason )
5032
+ self .assertNotEqual (0 , wrap_error .args [0 ])
5033
+ self .assertIsNone (wrap_error .library , msg = "attr must exist" )
5034
+ finally :
5035
+ # gh-108342: Explicitly break the reference cycle
5036
+ wrap_error = None
5037
+ server = None
5016
5038
5017
5039
def test_preauth_data_to_tls_client (self ):
5040
+ server_can_continue_with_wrap_socket = threading .Event ()
5018
5041
client_can_continue_with_wrap_socket = threading .Event ()
5019
5042
5020
5043
def call_after_accept (conn_to_client ):
5044
+ if not server_can_continue_with_wrap_socket .wait (support .SHORT_TIMEOUT ):
5045
+ print ("ERROR: test client took too long" )
5046
+
5021
5047
# This forces an immediate connection close via RST on .close().
5022
5048
set_socket_so_linger_on_with_zero_timeout (conn_to_client )
5023
5049
conn_to_client .send (
@@ -5037,8 +5063,10 @@ def call_after_accept(conn_to_client):
5037
5063
5038
5064
with socket .socket () as client :
5039
5065
client .connect (server .listener .getsockname ())
5040
- if not client_can_continue_with_wrap_socket .wait (2.0 ):
5041
- self .fail ("test server took too long." )
5066
+ server_can_continue_with_wrap_socket .set ()
5067
+
5068
+ if not client_can_continue_with_wrap_socket .wait (support .SHORT_TIMEOUT ):
5069
+ self .fail ("test server took too long" )
5042
5070
ssl_ctx = ssl .create_default_context ()
5043
5071
try :
5044
5072
tls_client = ssl_ctx .wrap_socket (
@@ -5052,24 +5080,31 @@ def call_after_accept(conn_to_client):
5052
5080
tls_client .close ()
5053
5081
5054
5082
server .join ()
5055
- self .assertEqual (b"" , received_data )
5056
- self .assertIsInstance (wrap_error , OSError ) # All platforms.
5057
- self .non_linux_skip_if_other_okay_error (wrap_error )
5058
- self .assertIsInstance (wrap_error , ssl .SSLError )
5059
- self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
5060
- self .assertIn ("before TLS handshake with data" , wrap_error .reason )
5061
- self .assertNotEqual (0 , wrap_error .args [0 ])
5062
- self .assertIsNone (wrap_error .library , msg = "attr must exist" )
5083
+ try :
5084
+ self .assertEqual (b"" , received_data )
5085
+ self .assertIsInstance (wrap_error , OSError ) # All platforms.
5086
+ self .non_linux_skip_if_other_okay_error (wrap_error )
5087
+ self .assertIsInstance (wrap_error , ssl .SSLError )
5088
+ self .assertIn ("before TLS handshake with data" , wrap_error .args [1 ])
5089
+ self .assertIn ("before TLS handshake with data" , wrap_error .reason )
5090
+ self .assertNotEqual (0 , wrap_error .args [0 ])
5091
+ self .assertIsNone (wrap_error .library , msg = "attr must exist" )
5092
+ finally :
5093
+ # gh-108342: Explicitly break the reference cycle
5094
+ wrap_error = None
5095
+ server = None
5063
5096
5064
5097
def test_https_client_non_tls_response_ignored (self ):
5065
-
5066
5098
server_responding = threading .Event ()
5067
5099
5068
5100
class SynchronizedHTTPSConnection (http .client .HTTPSConnection ):
5069
5101
def connect (self ):
5102
+ # Call clear text HTTP connect(), not the encrypted HTTPS (TLS)
5103
+ # connect(): wrap_socket() is called manually below.
5070
5104
http .client .HTTPConnection .connect (self )
5105
+
5071
5106
# Wait for our fault injection server to have done its thing.
5072
- if not server_responding .wait (1.0 ) and support .verbose :
5107
+ if not server_responding .wait (support . SHORT_TIMEOUT ) and support .verbose :
5073
5108
sys .stdout .write ("server_responding event never set." )
5074
5109
self .sock = self ._context .wrap_socket (
5075
5110
self .sock , server_hostname = self .host )
@@ -5084,28 +5119,33 @@ def call_after_accept(conn_to_client):
5084
5119
server_responding .set ()
5085
5120
return True # Tell the server to stop.
5086
5121
5122
+ timeout = 2.0
5087
5123
server = self .SingleConnectionTestServerThread (
5088
5124
call_after_accept = call_after_accept ,
5089
- name = "non_tls_http_RST_responder" )
5125
+ name = "non_tls_http_RST_responder" ,
5126
+ timeout = timeout )
5090
5127
self .enterContext (server ) # starts it & unittest.TestCase stops it.
5091
5128
# Redundant; call_after_accept sets SO_LINGER on the accepted conn.
5092
5129
set_socket_so_linger_on_with_zero_timeout (server .listener )
5093
5130
5094
5131
connection = SynchronizedHTTPSConnection (
5095
- f"localhost" ,
5132
+ server . listener . getsockname ()[ 0 ] ,
5096
5133
port = server .port ,
5097
5134
context = ssl .create_default_context (),
5098
- timeout = 2.0 ,
5135
+ timeout = timeout ,
5099
5136
)
5137
+
5100
5138
# There are lots of reasons this raises as desired, long before this
5101
5139
# test was added. Sending the request requires a successful TLS wrapped
5102
5140
# socket; that fails if the connection is broken. It may seem pointless
5103
5141
# to test this. It serves as an illustration of something that we never
5104
5142
# want to happen... properly not happening.
5105
- with self .assertRaises (OSError ) as err_ctx :
5143
+ with self .assertRaises (OSError ):
5106
5144
connection .request ("HEAD" , "/test" , headers = {"Host" : "localhost" })
5107
5145
response = connection .getresponse ()
5108
5146
5147
+ server .join ()
5148
+
5109
5149
5110
5150
class TestEnumerations (unittest .TestCase ):
5111
5151
0 commit comments