]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40280: Detect missing threading on WASM platforms (GH-32352)
authorChristian Heimes <christian@python.org>
Thu, 7 Apr 2022 07:22:47 +0000 (10:22 +0300)
committerGitHub <noreply@github.com>
Thu, 7 Apr 2022 07:22:47 +0000 (09:22 +0200)
Co-authored-by: Brett Cannon <brett@python.org>
33 files changed:
Lib/distutils/tests/test_build_ext.py
Lib/test/libregrtest/main.py
Lib/test/pickletester.py
Lib/test/support/threading_helper.py
Lib/test/test_bz2.py
Lib/test/test_capi.py
Lib/test/test_context.py
Lib/test/test_decimal.py
Lib/test/test_email/test_email.py
Lib/test/test_enum.py
Lib/test/test_functools.py
Lib/test/test_gc.py
Lib/test/test_hashlib.py
Lib/test/test_import/__init__.py
Lib/test/test_importlib/test_locks.py
Lib/test/test_importlib/test_threaded_import.py
Lib/test/test_io.py
Lib/test/test_itertools.py
Lib/test/test_logging.py
Lib/test/test_queue.py
Lib/test/test_sched.py
Lib/test/test_signal.py
Lib/test/test_support.py
Lib/test/test_sys.py
Lib/test/test_thread.py
Lib/test/test_threadedtempfile.py
Lib/test/test_threading.py
Lib/test/test_threading_local.py
Lib/test/test_threadsignals.py
Lib/test/test_weakref.py
Misc/NEWS.d/next/Tests/2022-04-06-10-16-27.bpo-40280.KT5Apg.rst [new file with mode: 0644]
configure
configure.ac

index 460b62f50bc12e3aba52ceb2cac964c5c814caaf..031897bd2734fa238c2a057cd647c16df3fbfcee 100644 (file)
@@ -17,6 +17,7 @@ import unittest
 from test import support
 from test.support import os_helper
 from test.support.script_helper import assert_python_ok
+from test.support import threading_helper
 
 # http://bugs.python.org/issue4373
 # Don't load the xx module more than once.
@@ -165,6 +166,7 @@ class BuildExtTestCase(TempdirManager,
         self.assertIn(lib, cmd.rpath)
         self.assertIn(incl, cmd.include_dirs)
 
+    @threading_helper.requires_working_threading()
     def test_optional_extension(self):
 
         # this extension will fail, but let's ignore this failure
index af58114ed925c14d198a21aa53984da1d59b568e..e7e3dde0b0a66dc9a621823e611807e5fb2e4620 100644 (file)
@@ -20,6 +20,7 @@ from test.libregrtest.pgo import setup_pgo_tests
 from test.libregrtest.utils import removepy, count, format_duration, printlist
 from test import support
 from test.support import os_helper
+from test.support import threading_helper
 
 
 # bpo-38203: Maximum delay in seconds to exit Python (call Py_Finalize()).
@@ -676,7 +677,8 @@ class Regrtest:
         except SystemExit as exc:
             # bpo-38203: Python can hang at exit in Py_Finalize(), especially
             # on threading._shutdown() call: put a timeout
-            faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True)
+            if threading_helper.can_start_thread:
+                faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True)
 
             sys.exit(exc.code)
 
index 63fa7604fbfc9e502acf0b12963f6068fdad2d94..d0ea7d0e55e7d543ab5e80f257a415b27518b76d 100644 (file)
@@ -1380,6 +1380,7 @@ class AbstractUnpickleTests:
             self.check_unpickling_error(self.truncated_errors, p)
 
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_unpickle_module_race(self):
         # https://bugs.python.org/issue34572
         locker_module = dedent("""
index 2ae4577f41f7be8abbff469d33a58f2fd6660aba..7b636f0ccf097b1542cd7cb3811fb03b99de7e78 100644 (file)
@@ -4,6 +4,7 @@ import functools
 import sys
 import threading
 import time
+import unittest
 
 from test import support
 
@@ -210,7 +211,7 @@ class catch_threading_exception:
 
 
 def _can_start_thread() -> bool:
-    """Detect if Python can start new threads.
+    """Detect whether Python can start new threads.
 
     Some WebAssembly platforms do not provide a working pthread
     implementation. Thread support is stubbed and any attempt
@@ -234,3 +235,15 @@ def _can_start_thread() -> bool:
         return True
 
 can_start_thread = _can_start_thread()
+
+def requires_working_threading(*, module=False):
+    """Skip tests or modules that require working threading.
+
+    Can be used as a function/class decorator or to skip an entire module.
+    """
+    msg = "requires threading support"
+    if module:
+        if not can_start_thread:
+            raise unittest.SkipTest(msg)
+    else:
+        return unittest.skipUnless(can_start_thread, msg)
index 9965c1fe2e5f17583f49450cffcaa806d777054f..c97ed1cea0d113bf2842f3c50a7950ebbf9549ee 100644 (file)
@@ -496,6 +496,7 @@ class BZ2FileTest(BaseTest):
         else:
             self.fail("1/0 didn't raise an exception")
 
+    @threading_helper.requires_working_threading()
     def testThreading(self):
         # Issue #7205: Using a BZ2File from several threads shouldn't deadlock.
         data = b"1" * 2**20
index 714a2d98e9fb5edec87d48e118d5b27fbbf0eaa3..3837f801b3c738f819d85df3cf8496ba9fd96df8 100644 (file)
@@ -710,6 +710,7 @@ class TestPendingCalls(unittest.TestCase):
         if False and support.verbose:
             print("(%i)"%(len(l),))
 
+    @threading_helper.requires_working_threading()
     def test_pendingcalls_threaded(self):
 
         #do every callback on a separate thread
@@ -840,6 +841,7 @@ class SubinterpreterTest(unittest.TestCase):
 class TestThreadState(unittest.TestCase):
 
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_thread_state(self):
         # some extra thread-state tests driven via _testcapi
         def target():
index 2d8b63a1f59581e1c471ca82dc8c13fb8fda3e71..3132cea668cb1b78666590f15eb26ddaff502bdc 100644 (file)
@@ -6,6 +6,7 @@ import random
 import time
 import unittest
 import weakref
+from test.support import threading_helper
 
 try:
     from _testcapi import hamt
@@ -341,6 +342,7 @@ class ContextTest(unittest.TestCase):
         ctx1.run(ctx1_fun)
 
     @isolated_context
+    @threading_helper.requires_working_threading()
     def test_context_threads_1(self):
         cvar = contextvars.ContextVar('cvar')
 
index b68cfbef23f16d50b77a2a0b6c65c9a4f48e84ed..0e7491ecdd45c48d1547e01541284b9ea18feb9c 100644 (file)
@@ -39,6 +39,7 @@ from test.support import (TestFailed,
                           run_with_locale, cpython_only,
                           darwin_malloc_err_warning)
 from test.support.import_helper import import_fresh_module
+from test.support import threading_helper
 from test.support import warnings_helper
 import random
 import inspect
@@ -1591,6 +1592,8 @@ def thfunc2(cls):
     for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
         cls.assertFalse(thiscontext.flags[sig])
 
+
+@threading_helper.requires_working_threading()
 class ThreadingTest(unittest.TestCase):
     '''Unit tests for thread local contexts in Decimal.'''
 
index a3ccbbbabfb328f25870df6b8d7750f044ee92f3..ca9c773bbc559a80090b779e7befc211998dc2d5 100644 (file)
@@ -3285,6 +3285,7 @@ Foo
         addrs = utils.getaddresses([Header('Al Person <aperson@dom.ain>')])
         self.assertEqual(addrs[0][1], 'aperson@dom.ain')
 
+    @threading_helper.requires_working_threading()
     def test_make_msgid_collisions(self):
         # Test make_msgid uniqueness, even with multiple threads
         class MsgidsThread(Thread):
index f2572b2ac351a763d0f328008ccb28816ec64dc7..b1b8e82b3859f2979a67447584a3b97d7b2907dc 100644 (file)
@@ -2949,6 +2949,7 @@ class OldTestFlag(unittest.TestCase):
         self.assertEqual(str(Color.BLUE), 'blue')
 
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_unique_composite(self):
         # override __eq__ to be identity only
         class TestFlag(Flag):
@@ -3481,6 +3482,7 @@ class OldTestIntFlag(unittest.TestCase):
         self.assertEqual(str(Color.BLUE), 'blue')
 
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_unique_composite(self):
         # override __eq__ to be identity only
         class TestFlag(IntFlag):
index 82e73f46a3fbae3db65c7c681df9b694228386d4..e3c065615778f9445d1a8015b99b98376b2788ed 100644 (file)
@@ -1637,6 +1637,7 @@ class TestLRU:
         for attr in self.module.WRAPPER_ASSIGNMENTS:
             self.assertEqual(getattr(g, attr), getattr(f, attr))
 
+    @threading_helper.requires_working_threading()
     def test_lru_cache_threaded(self):
         n, m = 5, 11
         def orig(x, y):
@@ -1685,6 +1686,7 @@ class TestLRU:
         finally:
             sys.setswitchinterval(orig_si)
 
+    @threading_helper.requires_working_threading()
     def test_lru_cache_threaded2(self):
         # Simultaneous call with the same arguments
         n, m = 5, 7
@@ -1712,6 +1714,7 @@ class TestLRU:
                 pause.reset()
                 self.assertEqual(f.cache_info(), (0, (i+1)*n, m*n, i+1))
 
+    @threading_helper.requires_working_threading()
     def test_lru_cache_threaded3(self):
         @self.module.lru_cache(maxsize=2)
         def f(x):
@@ -2914,6 +2917,7 @@ class TestCachedProperty(unittest.TestCase):
         self.assertEqual(item.get_cost(), 4)
         self.assertEqual(item.cached_cost, 3)
 
+    @threading_helper.requires_working_threading()
     def test_threaded(self):
         go = threading.Event()
         item = CachedCostItemWait(go)
index c4d4355dec9c6d87d6e462dbb10580a84d533671..ce04042679bbc2349c7382447822aca05ec9d7d3 100644 (file)
@@ -365,6 +365,7 @@ class GCTests(unittest.TestCase):
                 v = {1: v, 2: Ouch()}
         gc.disable()
 
+    @threading_helper.requires_working_threading()
     def test_trashcan_threads(self):
         # Issue #13992: trashcan mechanism should be thread-safe
         NESTING = 60
index d2a92147d5f0244ecf261fad7ab50dfcc99f3bdc..67becdd6d317f346d9ded20a2354f180cbb96845 100644 (file)
@@ -915,6 +915,7 @@ class HashLibTestCase(unittest.TestCase):
         )
 
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_threaded_hashing(self):
         # Updating the same hash object from several threads at once
         # using data chunk sizes containing the same byte sequences.
index 7cca9f9d60ab6ab827028bbdc3e5d141af08a63d..be88677dc697ee4fd4f5f500d10d9a2713cd2c4c 100644 (file)
@@ -448,6 +448,7 @@ class ImportTests(unittest.TestCase):
             with self.assertRaises(AttributeError):
                 os.does_not_exist
 
+    @threading_helper.requires_working_threading()
     def test_concurrency(self):
         # bpo 38091: this is a hack to slow down the code that calls
         # has_deadlock(); the logic was itself sometimes deadlocking.
index 584d013caacad94b3d00bf963afd0da164fc7106..56d73c496e6bbb01cda23eb287ccb0b2640e1db2 100644 (file)
@@ -12,6 +12,9 @@ from test.support import threading_helper
 from test import lock_tests
 
 
+threading_helper.requires_working_threading(module=True)
+
+
 class ModuleLockAsRLockTests:
     locktype = classmethod(lambda cls: cls.LockType("some_lock"))
 
@@ -146,4 +149,4 @@ def setUpModule():
 
 
 if __name__ == '__main__':
-    unittets.main()
+    unittest.main()
index 76b028eac97bf948127f9c1d459a9681f69b998e..cc1d804f35f913d0e2a9cebac489baf12dd997bb 100644 (file)
@@ -19,6 +19,8 @@ from test.support.import_helper import forget
 from test.support.os_helper import (TESTFN, unlink, rmtree)
 from test.support import script_helper, threading_helper
 
+threading_helper.requires_working_threading(module=True)
+
 def task(N, done, done_tasks, errors):
     try:
         # We don't use modulefinder but still import it in order to stress
index 67be108d2526f700f069e1f0c7dc88e5e02b86e7..29fe287550b2d0f3909aca85a1eb97fa674ec342 100644 (file)
@@ -1451,6 +1451,7 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
         self.assertEqual(b"abcdefg", bufio.read())
 
     @support.requires_resource('cpu')
+    @threading_helper.requires_working_threading()
     def test_threads(self):
         try:
             # Write out many bytes with exactly the same number of 0's,
@@ -1825,6 +1826,7 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
                 self.assertEqual(f.tell(), buffer_size + 2)
 
     @support.requires_resource('cpu')
+    @threading_helper.requires_working_threading()
     def test_threads(self):
         try:
             # Write out many bytes from many threads and test they were
@@ -1895,6 +1897,7 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
         self.assertRaises(OSError, b.close) # exception not swallowed
         self.assertTrue(b.closed)
 
+    @threading_helper.requires_working_threading()
     def test_slow_close_from_thread(self):
         # Issue #31976
         rawio = self.SlowFlushRawIO()
@@ -3287,6 +3290,7 @@ class TextIOWrapperTest(unittest.TestCase):
             self.assertEqual(f.errors, "replace")
 
     @support.no_tracing
+    @threading_helper.requires_working_threading()
     def test_threads_write(self):
         # Issue6750: concurrent writes could duplicate data
         event = threading.Event()
@@ -4362,9 +4366,11 @@ class CMiscIOTest(MiscIOTest):
         else:
             self.assertFalse(err.strip('.!'))
 
+    @threading_helper.requires_working_threading()
     def test_daemon_threads_shutdown_stdout_deadlock(self):
         self.check_daemon_threads_shutdown_deadlock('stdout')
 
+    @threading_helper.requires_working_threading()
     def test_daemon_threads_shutdown_stderr_deadlock(self):
         self.check_daemon_threads_shutdown_deadlock('stderr')
 
index 3f3f7cb35d0bc78002b09bb92c4af38c2bd62c21..238afbbd883d3a2b63b6aaf1cba7c816258d223e 100644 (file)
@@ -1,6 +1,7 @@
 import doctest
 import unittest
 from test import support
+from test.support import threading_helper
 from itertools import *
 import weakref
 from decimal import Decimal
@@ -1533,6 +1534,7 @@ class TestBasicOps(unittest.TestCase):
         with self.assertRaisesRegex(RuntimeError, "tee"):
             next(a)
 
+    @threading_helper.requires_working_threading()
     def test_tee_concurrent(self):
         start = threading.Event()
         finish = threading.Event()
index f6f5977df2a1ee5d4ba131e8ac61166bc8948dc0..7555f05d1d0cf9a845d46ede8a0bb36062f90011 100644 (file)
@@ -630,6 +630,7 @@ class HandlerTest(BaseTest):
     @unittest.skipIf(
         support.is_emscripten, "Emscripten cannot fstat unlinked files."
     )
+    @threading_helper.requires_working_threading()
     def test_race(self):
         # Issue #14632 refers.
         def remove_loop(fname, tries):
@@ -679,6 +680,7 @@ class HandlerTest(BaseTest):
     # This helps ensure that when fork exists (the important concept) that the
     # register_at_fork mechanism is also present and used.
     @support.requires_fork()
+    @threading_helper.requires_working_threading()
     def test_post_fork_child_no_deadlock(self):
         """Ensure child logging locks are not held; bpo-6721 & bpo-36533."""
         class _OurHandler(logging.Handler):
@@ -1063,6 +1065,7 @@ if hasattr(socket, "AF_UNIX"):
 # - end of server_helper section
 
 @support.requires_working_socket()
+@threading_helper.requires_working_threading()
 class SMTPHandlerTest(BaseTest):
     # bpo-14314, bpo-19665, bpo-34092: don't wait forever
     TIMEOUT = support.LONG_TIMEOUT
@@ -1172,6 +1175,7 @@ class MemoryHandlerTest(BaseTest):
         # assert that no new lines have been added
         self.assert_log_lines(lines)  # no change
 
+    @threading_helper.requires_working_threading()
     def test_race_between_set_target_and_flush(self):
         class MockRaceConditionHandler:
             def __init__(self, mem_hdlr):
@@ -1687,6 +1691,7 @@ class ConfigFileTest(BaseTest):
 
 
 @support.requires_working_socket()
+@threading_helper.requires_working_threading()
 class SocketHandlerTest(BaseTest):
 
     """Test for SocketHandler objects."""
@@ -1802,6 +1807,7 @@ class UnixSocketHandlerTest(SocketHandlerTest):
         os_helper.unlink(self.address)
 
 @support.requires_working_socket()
+@threading_helper.requires_working_threading()
 class DatagramHandlerTest(BaseTest):
 
     """Test for DatagramHandler."""
@@ -1884,6 +1890,7 @@ class UnixDatagramHandlerTest(DatagramHandlerTest):
         os_helper.unlink(self.address)
 
 @support.requires_working_socket()
+@threading_helper.requires_working_threading()
 class SysLogHandlerTest(BaseTest):
 
     """Test for SysLogHandler using UDP."""
@@ -1994,6 +2001,7 @@ class IPv6SysLogHandlerTest(SysLogHandlerTest):
         super(IPv6SysLogHandlerTest, self).tearDown()
 
 @support.requires_working_socket()
+@threading_helper.requires_working_threading()
 class HTTPHandlerTest(BaseTest):
     """Test for HTTPHandler."""
 
@@ -3575,6 +3583,7 @@ class LogRecordFactoryTest(BaseTest):
         ])
 
 
+@threading_helper.requires_working_threading()
 class QueueHandlerTest(BaseTest):
     # Do not bother with a logger name group.
     expected_log_pat = r"^[\w.]+ -> (\w+): (\d+)$"
@@ -3684,6 +3693,7 @@ if hasattr(logging.handlers, 'QueueListener'):
     import multiprocessing
     from unittest.mock import patch
 
+    @threading_helper.requires_working_threading()
     class QueueListenerTest(BaseTest):
         """
         Tests based on patch submitted for issue #27930. Ensure that
index cfa6003a867dafc8e27afcb402d62485f40b2545..e3080376a9de5fdba6fffe9cc9607a6736e6291d 100644 (file)
@@ -87,6 +87,7 @@ class BlockingTestMixin:
                 self.fail("trigger thread ended but event never set")
 
 
+@threading_helper.requires_working_threading()
 class BaseQueueTestMixin(BlockingTestMixin):
     def setUp(self):
         self.cum = 0
@@ -289,6 +290,8 @@ class CPriorityQueueTest(PriorityQueueTest, unittest.TestCase):
 # A Queue subclass that can provoke failure at a moment's notice :)
 class FailingQueueException(Exception): pass
 
+
+@threading_helper.requires_working_threading()
 class FailingQueueTest(BlockingTestMixin):
 
     def setUp(self):
@@ -464,6 +467,7 @@ class BaseSimpleQueueTest:
                 return
             results.append(val)
 
+    @threading_helper.requires_working_threading()
     def run_threads(self, n_threads, q, inputs, feed_func, consume_func):
         results = []
         sentinel = None
index 7ae7baae85e2c9ac02538950e30ed3ffe53020e8..32cc8105bc0557d4f7dcbc8bf37a5e32997edf42 100644 (file)
@@ -58,6 +58,7 @@ class TestCase(unittest.TestCase):
         scheduler.run()
         self.assertEqual(l, [0.01, 0.02, 0.03, 0.04, 0.05])
 
+    @threading_helper.requires_working_threading()
     def test_enter_concurrent(self):
         q = queue.Queue()
         fun = q.put
@@ -111,6 +112,7 @@ class TestCase(unittest.TestCase):
         scheduler.run()
         self.assertEqual(l, [0.02, 0.03, 0.04])
 
+    @threading_helper.requires_working_threading()
     def test_cancel_concurrent(self):
         q = queue.Queue()
         fun = q.put
index 37b46065e532c2e87a6d21c161466eb957bd5ba9..ea13c59ec711e607f69bcb7982e71f4f457efdf5 100644 (file)
@@ -14,6 +14,7 @@ import unittest
 from test import support
 from test.support import os_helper
 from test.support.script_helper import assert_python_ok, spawn_python
+from test.support import threading_helper
 try:
     import _testcapi
 except ImportError:
@@ -876,6 +877,7 @@ class PendingSignalsTests(unittest.TestCase):
 
     @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
                          'need signal.pthread_kill()')
+    @threading_helper.requires_working_threading()
     def test_pthread_kill(self):
         code = """if 1:
             import signal
@@ -1012,6 +1014,7 @@ class PendingSignalsTests(unittest.TestCase):
                          'need signal.sigwait()')
     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
                          'need signal.pthread_sigmask()')
+    @threading_helper.requires_working_threading()
     def test_sigwait_thread(self):
         # Check that calling sigwait() from a thread doesn't suspend the whole
         # process. A new interpreter is spawned to avoid problems when mixing
@@ -1067,6 +1070,7 @@ class PendingSignalsTests(unittest.TestCase):
 
     @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
                          'need signal.pthread_sigmask()')
+    @threading_helper.requires_working_threading()
     def test_pthread_sigmask(self):
         code = """if 1:
         import signal
@@ -1144,6 +1148,7 @@ class PendingSignalsTests(unittest.TestCase):
 
     @unittest.skipUnless(hasattr(signal, 'pthread_kill'),
                          'need signal.pthread_kill()')
+    @threading_helper.requires_working_threading()
     def test_pthread_kill_main_thread(self):
         # Test that a signal can be sent to the main thread with pthread_kill()
         # before any other thread has been created (see issue #12392).
@@ -1298,6 +1303,7 @@ class StressTest(unittest.TestCase):
 
     @unittest.skipUnless(hasattr(signal, "SIGUSR1"),
                          "test needs SIGUSR1")
+    @threading_helper.requires_working_threading()
     def test_stress_modifying_handlers(self):
         # bpo-43406: race condition between trip_signal() and signal.signal
         signum = signal.SIGUSR1
index 2cff377cf629ebf4785c93061ec04aa592abf384..90e971deb397f28a810371616abbf058d055eab8 100644 (file)
@@ -123,15 +123,18 @@ class TestSupport(unittest.TestCase):
             os_helper.unlink(mod_filename)
             os_helper.rmtree('__pycache__')
 
+    @support.requires_working_socket()
     def test_HOST(self):
         s = socket.create_server((socket_helper.HOST, 0))
         s.close()
 
+    @support.requires_working_socket()
     def test_find_unused_port(self):
         port = socket_helper.find_unused_port()
         s = socket.create_server((socket_helper.HOST, port))
         s.close()
 
+    @support.requires_working_socket()
     def test_bind_port(self):
         s = socket.socket()
         socket_helper.bind_port(s)
index 445ff893ff6fcf3ec5310f9d74c6d97f2963041b..b70871ff551d9a523442833216df1555bb3f9137 100644 (file)
@@ -401,6 +401,7 @@ class SysModuleTest(unittest.TestCase):
 
     # sys._current_frames() is a CPython-only gimmick.
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_current_frames(self):
         import threading
         import traceback
@@ -466,6 +467,7 @@ class SysModuleTest(unittest.TestCase):
         t.join()
 
     @threading_helper.reap_threads
+    @threading_helper.requires_working_threading()
     def test_current_exceptions(self):
         import threading
         import traceback
@@ -1176,11 +1178,12 @@ class UnraisableHookTest(unittest.TestCase):
         for moduleName in 'builtins', '__main__', 'some_module':
             with self.subTest(moduleName=moduleName):
                 A.B.X.__module__ = moduleName
-                with test.support.captured_stderr() as stderr, \
-                     test.support.swap_attr(sys, 'unraisablehook',
-                                            sys.__unraisablehook__):
+                with test.support.captured_stderr() as stderr, test.support.swap_attr(
+                    sys, 'unraisablehook', sys.__unraisablehook__
+                ):
                     expected = self.write_unraisable_exc(
-                        A.B.X(), "msg", "obj");
+                        A.B.X(), "msg", "obj"
+                    )
                 report = stderr.getvalue()
                 self.assertIn(A.B.X.__qualname__, report)
                 if moduleName in ['builtins', '__main__']:
index d55fb731b6df54c0d5cd6b52f749abb18957a292..ed527e7164fd0a4860aab0d4c78da8079f985bd9 100644 (file)
@@ -9,6 +9,8 @@ import weakref
 
 from test import lock_tests
 
+threading_helper.requires_working_threading(module=True)
+
 NUMTASKS = 10
 NUMTRIPS = 3
 POLL_SLEEP = 0.010 # seconds = 10 ms
index fe63c9e91437bac33f7f2f45b3948ea3a853f049..420fc6ec8be3d8d9e7f6b85616fde730da445b24 100644 (file)
@@ -21,6 +21,7 @@ import io
 import threading
 from traceback import print_exc
 
+threading_helper.requires_working_threading(module=True)
 
 NUM_THREADS = 20
 FILES_PER_THREAD = 50
index 16c6934c6d432b8e227fad485dcc720b64f1ab4d..f7dea136a87c0d23836072f1c27d7aea41c7d7f8 100644 (file)
@@ -25,6 +25,7 @@ from unittest import mock
 from test import lock_tests
 from test import support
 
+threading_helper.requires_working_threading(module=True)
 
 # Between fork() and exec(), only async-safe functions are allowed (issues
 # #12316 and #11870), and fork() from a worker thread is known to trigger
index 1567c41000bc59470f4134c1fd83b82a3d487071..9888e631881fa6813a950463aea8d21a80fcebe2 100644 (file)
@@ -12,6 +12,9 @@ import threading
 import _threading_local
 
 
+threading_helper.requires_working_threading(module=True)
+
+
 class Weak(object):
     pass
 
index bac82b8a4451137930b19bd296cfde202c2b87b0..e0ac18c9463986a3e82e9c02b7130f30f3aa5df8 100644 (file)
@@ -36,6 +36,7 @@ def send_signals():
     os.kill(process_pid, signal.SIGUSR2)
     signalled_all.release()
 
+@threading_helper.requires_working_threading()
 class ThreadSignals(unittest.TestCase):
 
     def test_signals(self):
index 46dac0228295d74a821d847aae7001e09831494d..702bb4495e74994b60e405fa5ed1a72b46658589 100644 (file)
@@ -14,6 +14,7 @@ import random
 from test import support
 from test.support import script_helper, ALWAYS_EQ
 from test.support import gc_collect
+from test.support import threading_helper
 
 # Used in ReferencesTestCase.test_ref_created_during_del() .
 ref_from_del = None
@@ -1851,6 +1852,7 @@ class MappingTestCase(TestBase):
         dict = weakref.WeakKeyDictionary()
         self.assertRegex(repr(dict), '<WeakKeyDictionary at 0x.*>')
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_valued_setdefault(self):
         d = weakref.WeakValueDictionary()
         with collect_in_thread():
@@ -1859,6 +1861,7 @@ class MappingTestCase(TestBase):
                 self.assertIsNot(x, None)  # we never put None in there!
                 del x
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_valued_pop(self):
         d = weakref.WeakValueDictionary()
         with collect_in_thread():
@@ -1867,6 +1870,7 @@ class MappingTestCase(TestBase):
                 x = d.pop(10, 10)
                 self.assertIsNot(x, None)  # we never put None in there!
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_valued_consistency(self):
         # Issue #28427: old keys should not remove new values from
         # WeakValueDictionary when collecting from another thread.
@@ -1940,21 +1944,25 @@ class MappingTestCase(TestBase):
         if exc:
             raise exc[0]
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_key_dict_copy(self):
         # Issue #35615: Weakref keys or values getting GC'ed during dict
         # copying should not result in a crash.
         self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, False)
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_key_dict_deepcopy(self):
         # Issue #35615: Weakref keys or values getting GC'ed during dict
         # copying should not result in a crash.
         self.check_threaded_weak_dict_copy(weakref.WeakKeyDictionary, True)
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_value_dict_copy(self):
         # Issue #35615: Weakref keys or values getting GC'ed during dict
         # copying should not result in a crash.
         self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, False)
 
+    @threading_helper.requires_working_threading()
     def test_threaded_weak_value_dict_deepcopy(self):
         # Issue #35615: Weakref keys or values getting GC'ed during dict
         # copying should not result in a crash.
diff --git a/Misc/NEWS.d/next/Tests/2022-04-06-10-16-27.bpo-40280.KT5Apg.rst b/Misc/NEWS.d/next/Tests/2022-04-06-10-16-27.bpo-40280.KT5Apg.rst
new file mode 100644 (file)
index 0000000..9fcb4c9
--- /dev/null
@@ -0,0 +1 @@
+Threading tests are now skipped on WASM targets without pthread support.
index e10462cf4dbfc56809f5bed09938d953c8999a28..69b12309de57895915b7e905d7e0bbf3b5ea369b 100755 (executable)
--- a/configure
+++ b/configure
@@ -6311,15 +6311,7 @@ esac
 
 else
 
-  case $ac_sys_system in #(
-  Emscripten) :
-    enable_wasm_dynamic_linking=no ;; #(
-  WASI) :
-    enable_wasm_dynamic_linking=no ;; #(
-  *) :
-    enable_wasm_dynamic_linking=missing
-   ;;
-esac
+  enable_wasm_dynamic_linking=missing
 
 fi
 
index 4f256eeff5d7bda8bfa6424038fb572ac1ceb4b3..5860595b752c8ccdb97938b79822b9848ffaa0d6 100644 (file)
@@ -1122,11 +1122,7 @@ AC_ARG_ENABLE([wasm-dynamic-linking],
     [AC_MSG_ERROR([--enable-wasm-dynamic-linking only applies to Emscripten and WASI])]
   )
 ], [
-  AS_CASE([$ac_sys_system],
-    [Emscripten], [enable_wasm_dynamic_linking=no],
-    [WASI], [enable_wasm_dynamic_linking=no],
-    [enable_wasm_dynamic_linking=missing]
-  )
+  enable_wasm_dynamic_linking=missing
 ])
 AC_MSG_RESULT([$enable_wasm_dynamic_linking])