3
3
import sys
4
4
import unittest
5
5
import unittest .mock
6
+ from ast import literal_eval
7
+ from threading import Thread
6
8
from test import support
7
9
from test .support import import_helper
8
10
from test .support import os_helper
@@ -304,11 +306,19 @@ def test_wrap_socket(sock, *,
304
306
return context .wrap_socket (sock ,** kwargs )
305
307
306
308
309
+ USE_SAME_TEST_CONTEXT = False
310
+ _TEST_CONTEXT = None
311
+
307
312
def testing_context (server_cert = SIGNED_CERTFILE ,* ,server_chain = True ):
308
313
"""Create context
309
314
310
315
client_context, server_context, hostname = testing_context()
311
316
"""
317
+ global _TEST_CONTEXT
318
+ if USE_SAME_TEST_CONTEXT :
319
+ if _TEST_CONTEXT is not None :
320
+ return _TEST_CONTEXT
321
+
312
322
if server_cert == SIGNED_CERTFILE :
313
323
hostname = SIGNED_CERTFILE_HOSTNAME
314
324
elif server_cert == SIGNED_CERTFILE2 :
@@ -326,6 +336,10 @@ def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True):
326
336
if server_chain :
327
337
server_context .load_verify_locations (SIGNING_CA )
328
338
339
+ if USE_SAME_TEST_CONTEXT :
340
+ if _TEST_CONTEXT is not None :
341
+ _TEST_CONTEXT = client_context ,server_context ,hostname
342
+
329
343
return client_context ,server_context ,hostname
330
344
331
345
@@ -2834,6 +2848,44 @@ def test_echo(self):
2834
2848
'Cannot create a client socket with a PROTOCOL_TLS_SERVER context' ,
2835
2849
str (e .exception ))
2836
2850
2851
+ @unittest .skipUnless (support .Py_GIL_DISABLED ,"test is only useful if the GIL is disabled" )
2852
+ def test_ssl_in_multiple_threads (self ):
2853
+ # See GH-124984: OpenSSL is not thread safe.
2854
+ threads = []
2855
+
2856
+ global USE_SAME_TEST_CONTEXT
2857
+ USE_SAME_TEST_CONTEXT = True
2858
+ try :
2859
+ for func in (
2860
+ self .test_echo ,
2861
+ self .test_alpn_protocols ,
2862
+ self .test_getpeercert ,
2863
+ self .test_crl_check ,
2864
+ self .test_check_hostname_idn ,
2865
+ self .test_wrong_cert_tls12 ,
2866
+ self .test_wrong_cert_tls13 ,
2867
+ ):
2868
+ # Be careful with the number of threads here.
2869
+ # Too many can result in failing tests.
2870
+ for num in range (5 ):
2871
+ with self .subTest (func = func ,num = num ):
2872
+ threads .append (Thread (target = func ))
2873
+
2874
+ with threading_helper .catch_threading_exception ()as cm :
2875
+ for thread in threads :
2876
+ with self .subTest (thread = thread ):
2877
+ thread .start ()
2878
+
2879
+ for thread in threads :
2880
+ with self .subTest (thread = thread ):
2881
+ thread .join ()
2882
+ if cm .exc_value is not None :
2883
+ # Some threads can skip their test
2884
+ if not isinstance (cm .exc_value ,unittest .SkipTest ):
2885
+ raise cm .exc_value
2886
+ finally :
2887
+ USE_SAME_TEST_CONTEXT = False
2888
+
2837
2889
def test_getpeercert (self ):
2838
2890
if support .verbose :
2839
2891
sys .stdout .write ("\n " )