Skip to content

Commit adfd6c7

Browse files
committed
More multiprocessing & concurrent.futures disables when forkserver cannot work
1 parent 7474d73 commit adfd6c7

File tree

4 files changed

+37
-7
lines changed

4 files changed

+37
-7
lines changed

Lib/test/_test_multiprocessing.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,7 @@ def _acquire_event(lock, event):
14311431
event.set()
14321432
time.sleep(1.0)
14331433

1434+
@hashlib_helper.requires_hashdigest('sha256') # Manager RPC connection auth
14341435
def test_repr_lock(self):
14351436
if self.TYPE != 'processes':
14361437
self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -1496,6 +1497,7 @@ def _acquire_release(lock, timeout, l=None, n=1):
14961497
for _ in range(n):
14971498
lock.release()
14981499

1500+
@hashlib_helper.requires_hashdigest('sha256') # Manager RPC connection auth
14991501
def test_repr_rlock(self):
15001502
if self.TYPE != 'processes':
15011503
self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -3417,6 +3419,7 @@ def tearDown(self):
34173419
self.mgr.shutdown()
34183420
self.mgr.join()
34193421

3422+
@hashlib_helper.requires_hashdigest('sha256') # multiprocessing.connection
34203423
def test_queue_get(self):
34213424
queue = self.mgr.Queue()
34223425
if gc.isenabled():
@@ -3730,6 +3733,7 @@ def test_context(self):
37303733
if self.TYPE == 'processes':
37313734
self.assertRaises(OSError, l.accept)
37323735

3736+
@hashlib_helper.requires_hashdigest('sha256') # connection auth
37333737
def test_empty_authkey(self):
37343738
# bpo-43952: allow empty bytes as authkey
37353739
def handler(*args):
@@ -5782,9 +5786,11 @@ def test_get_all_start_methods(self):
57825786
self.assertIn(methods[0], {'forkserver', 'spawn'},
57835787
msg='3.14+ default must not be fork')
57845788
if methods[0] == 'spawn':
5785-
# Confirm that the current default selection logic prefers
5786-
# forkserver vs spawn when available.
5787-
self.assertNotIn('forkserver', methods)
5789+
if not hashlib_helper.in_openssl_fips_mode():
5790+
# Confirm that the current default selection logic prefers
5791+
# forkserver vs spawn when available.
5792+
# OpenSSL FIPS mode can disable this by blocking sha256.
5793+
self.assertNotIn('forkserver', methods)
57885794

57895795
def test_preload_resources(self):
57905796
if multiprocessing.get_start_method() != 'forkserver':
@@ -5805,7 +5811,11 @@ def test_mixed_startmethod(self):
58055811
# Fork-based locks cannot be used with spawned process
58065812
for process_method in ["spawn", "forkserver"]:
58075813
queue = multiprocessing.get_context("fork").Queue()
5808-
process_ctx = multiprocessing.get_context(process_method)
5814+
try:
5815+
process_ctx = multiprocessing.get_context(process_method)
5816+
except ValueError as err:
5817+
self.skipTest(err)
5818+
continue
58095819
p = process_ctx.Process(target=close_queue, args=(queue,))
58105820
err_msg = "A SemLock created in a fork"
58115821
with self.assertRaisesRegex(RuntimeError, err_msg):
@@ -5814,8 +5824,13 @@ def test_mixed_startmethod(self):
58145824
# non-fork-based locks can be used with all other start methods
58155825
for queue_method in ["spawn", "forkserver"]:
58165826
for process_method in multiprocessing.get_all_start_methods():
5817-
queue = multiprocessing.get_context(queue_method).Queue()
5818-
process_ctx = multiprocessing.get_context(process_method)
5827+
try:
5828+
queue_ctx = multiprocessing.get_context(queue_method)
5829+
process_ctx = multiprocessing.get_context(process_method)
5830+
except ValueError as err:
5831+
self.skipTest(err)
5832+
continue
5833+
queue = queue_ctx.Queue()
58195834
p = process_ctx.Process(target=close_queue, args=(queue,))
58205835
p.start()
58215836
p.join()

Lib/test/support/hashlib_helper.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
_hashlib = None
99

1010

11+
def in_openssl_fips_mode() -> bool:
12+
"""Is OpenSSL based _hashlib is present & operating in FIPS mode?"""
13+
if _hashlib and _hashlib.get_fips_mode() != 0:
14+
return True
15+
return False
16+
17+
1118
def requires_hashdigest(digestname, openssl=None, usedforsecurity=True):
1219
"""Decorator raising SkipTest if a hashing algorithm is not available
1320

Lib/test/test_concurrent_futures/test_init.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ def test_spawn(self):
141141

142142
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
143143
def test_forkserver(self):
144+
import multiprocessing
145+
try:
146+
multiprocessing.get_context("forkserver")
147+
except ValueError as err:
148+
self.skipTest(str(err))
144149
self._test(ProcessPoolForkserverFailingInitializerTest)
145150

146151

Lib/test/test_concurrent_futures/util.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,10 @@ def get_context(self):
119119
self.skipTest("require unix system")
120120
if support.check_sanitizer(thread=True):
121121
self.skipTest("TSAN doesn't support threads after fork")
122-
return super().get_context()
122+
try:
123+
return super().get_context()
124+
except ValueError as err:
125+
self.skipTest(str(err))
123126

124127

125128
def create_executor_tests(remote_globals, mixin, bases=(BaseTestCase,),

0 commit comments

Comments
 (0)