Skip to content

Commit 2b16a08

Browse files
tiranbrettcannon
andauthored
bpo-40280: Detect missing threading on WASM platforms (GH-32352)
Co-authored-by: Brett Cannon <[email protected]>
1 parent 5aee46b commit 2b16a08

33 files changed

+103
-21
lines changed

Lib/distutils/tests/test_build_ext.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from test import support
1818
from test.support import os_helper
1919
from test.support.script_helper import assert_python_ok
20+
from test.support import threading_helper
2021

2122
# http://bugs.python.org/issue4373
2223
# Don't load the xx module more than once.
@@ -165,6 +166,7 @@ def test_user_site(self):
165166
self.assertIn(lib, cmd.rpath)
166167
self.assertIn(incl, cmd.include_dirs)
167168

169+
@threading_helper.requires_working_threading()
168170
def test_optional_extension(self):
169171

170172
# this extension will fail, but let's ignore this failure

Lib/test/libregrtest/main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from test.libregrtest.utils import removepy, count, format_duration, printlist
2121
from test import support
2222
from test.support import os_helper
23+
from test.support import threading_helper
2324

2425

2526
# bpo-38203: Maximum delay in seconds to exit Python (call Py_Finalize()).
@@ -676,7 +677,8 @@ def main(self, tests=None, **kwargs):
676677
except SystemExit as exc:
677678
# bpo-38203: Python can hang at exit in Py_Finalize(), especially
678679
# on threading._shutdown() call: put a timeout
679-
faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True)
680+
if threading_helper.can_start_thread:
681+
faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True)
680682

681683
sys.exit(exc.code)
682684

Lib/test/pickletester.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,7 @@ def test_truncated_data(self):
13801380
self.check_unpickling_error(self.truncated_errors, p)
13811381

13821382
@threading_helper.reap_threads
1383+
@threading_helper.requires_working_threading()
13831384
def test_unpickle_module_race(self):
13841385
# https://bugs.python.org/issue34572
13851386
locker_module = dedent("""

Lib/test/support/threading_helper.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import threading
66
import time
7+
import unittest
78

89
from test import support
910

@@ -210,7 +211,7 @@ def __exit__(self, *exc_info):
210211

211212

212213
def _can_start_thread() -> bool:
213-
"""Detect if Python can start new threads.
214+
"""Detect whether Python can start new threads.
214215
215216
Some WebAssembly platforms do not provide a working pthread
216217
implementation. Thread support is stubbed and any attempt
@@ -234,3 +235,15 @@ def _can_start_thread() -> bool:
234235
return True
235236

236237
can_start_thread = _can_start_thread()
238+
239+
def requires_working_threading(*, module=False):
240+
"""Skip tests or modules that require working threading.
241+
242+
Can be used as a function/class decorator or to skip an entire module.
243+
"""
244+
msg = "requires threading support"
245+
if module:
246+
if not can_start_thread:
247+
raise unittest.SkipTest(msg)
248+
else:
249+
return unittest.skipUnless(can_start_thread, msg)

Lib/test/test_bz2.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ def testContextProtocol(self):
496496
else:
497497
self.fail("1/0 didn't raise an exception")
498498

499+
@threading_helper.requires_working_threading()
499500
def testThreading(self):
500501
# Issue #7205: Using a BZ2File from several threads shouldn't deadlock.
501502
data = b"1" * 2**20

Lib/test/test_capi.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ def pendingcalls_wait(self, l, n, context = None):
710710
if False and support.verbose:
711711
print("(%i)"%(len(l),))
712712

713+
@threading_helper.requires_working_threading()
713714
def test_pendingcalls_threaded(self):
714715

715716
#do every callback on a separate thread
@@ -840,6 +841,7 @@ def test_module_state_shared_in_global(self):
840841
class TestThreadState(unittest.TestCase):
841842

842843
@threading_helper.reap_threads
844+
@threading_helper.requires_working_threading()
843845
def test_thread_state(self):
844846
# some extra thread-state tests driven via _testcapi
845847
def target():

Lib/test/test_context.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import time
77
import unittest
88
import weakref
9+
from test.support import threading_helper
910

1011
try:
1112
from _testcapi import hamt
@@ -341,6 +342,7 @@ def ctx2_fun():
341342
ctx1.run(ctx1_fun)
342343

343344
@isolated_context
345+
@threading_helper.requires_working_threading()
344346
def test_context_threads_1(self):
345347
cvar = contextvars.ContextVar('cvar')
346348

Lib/test/test_decimal.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
run_with_locale, cpython_only,
4040
darwin_malloc_err_warning)
4141
from test.support.import_helper import import_fresh_module
42+
from test.support import threading_helper
4243
from test.support import warnings_helper
4344
import random
4445
import inspect
@@ -1591,6 +1592,8 @@ def thfunc2(cls):
15911592
for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
15921593
cls.assertFalse(thiscontext.flags[sig])
15931594

1595+
1596+
@threading_helper.requires_working_threading()
15941597
class ThreadingTest(unittest.TestCase):
15951598
'''Unit tests for thread local contexts in Decimal.'''
15961599

Lib/test/test_email/test_email.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,6 +3285,7 @@ def test_getaddresses_header_obj(self):
32853285
addrs = utils.getaddresses([Header('Al Person <[email protected]>')])
32863286
self.assertEqual(addrs[0][1], '[email protected]')
32873287

3288+
@threading_helper.requires_working_threading()
32883289
def test_make_msgid_collisions(self):
32893290
# Test make_msgid uniqueness, even with multiple threads
32903291
class MsgidsThread(Thread):

Lib/test/test_enum.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,6 +2949,7 @@ class Color(StrMixin, AllMixin, Flag):
29492949
self.assertEqual(str(Color.BLUE), 'blue')
29502950

29512951
@threading_helper.reap_threads
2952+
@threading_helper.requires_working_threading()
29522953
def test_unique_composite(self):
29532954
# override __eq__ to be identity only
29542955
class TestFlag(Flag):
@@ -3481,6 +3482,7 @@ class Color(StrMixin, AllMixin, IntFlag):
34813482
self.assertEqual(str(Color.BLUE), 'blue')
34823483

34833484
@threading_helper.reap_threads
3485+
@threading_helper.requires_working_threading()
34843486
def test_unique_composite(self):
34853487
# override __eq__ to be identity only
34863488
class TestFlag(IntFlag):

0 commit comments

Comments
 (0)