]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38377: Add support.skip_if_broken_multiprocessing_synchronize() (GH-20944)
authorVictor Stinner <vstinner@python.org>
Thu, 18 Jun 2020 12:53:19 +0000 (14:53 +0200)
committerGitHub <noreply@github.com>
Thu, 18 Jun 2020 12:53:19 +0000 (14:53 +0200)
On Linux, skip tests using multiprocessing if the current user cannot
create a file in /dev/shm/ directory. Add the
skip_if_broken_multiprocessing_synchronize() function to the
test.support module.

Doc/library/test.rst
Lib/test/_test_multiprocessing.py
Lib/test/support/__init__.py
Lib/test/test_asyncio/test_events.py
Lib/test/test_concurrent_futures.py
Lib/test/test_logging.py
Lib/test/test_multiprocessing_main_handling.py
Lib/test/test_venv.py
Misc/NEWS.d/next/Tests/2020-06-17-18-00-21.bpo-38377.jfg4TH.rst [new file with mode: 0644]

index b39b601fb64f6981faeac93965c80ba4107452e2..cd05ef07b4a21218309262d5f960f57b6fcdd1b4 100644 (file)
@@ -919,6 +919,14 @@ The :mod:`test.support` module defines the following functions:
 
    .. versionadded:: 3.6
 
+.. function:: skip_if_broken_multiprocessing_synchronize()
+
+   Skip tests if the :mod:`multiprocessing.synchronize` module is missing, if
+   there is no available semaphore implementation, or if creating a lock raises
+   an :exc:`OSError`.
+
+   .. versionadded:: 3.10
+
 
 The :mod:`test.support` module defines the following classes:
 
index d01a6680e409cb430b80ff8400a9ad0cfb2957fb..444e234509c27342dcd11fc664c1e6fa5eb29ebb 100644 (file)
@@ -34,7 +34,7 @@ from test.support import threading_helper
 # Skip tests if _multiprocessing wasn't built.
 _multiprocessing = test.support.import_module('_multiprocessing')
 # Skip tests if sem_open implementation is broken.
-test.support.import_module('multiprocessing.synchronize')
+support.skip_if_broken_multiprocessing_synchronize()
 import threading
 
 import multiprocessing.connection
index da63d9281b107098d396f84de955cf1d84178c7b..d9dbdc13008dcc234f0cba03d2296cc2029cf2e2 100644 (file)
@@ -1957,3 +1957,25 @@ def wait_process(pid, *, exitcode, timeout=None):
     # sanity check: it should not fail in practice
     if pid2 != pid:
         raise AssertionError(f"pid {pid2} != pid {pid}")
+
+def skip_if_broken_multiprocessing_synchronize():
+    """
+    Skip tests if the multiprocessing.synchronize module is missing, if there
+    is no available semaphore implementation, or if creating a lock raises an
+    OSError.
+    """
+
+    # Skip tests if the _multiprocessing extension is missing.
+    import_module('_multiprocessing')
+
+    # Skip tests if there is no available semaphore implementation:
+    # multiprocessing.synchronize requires _multiprocessing.SemLock.
+    synchronize = import_module('multiprocessing.synchronize')
+
+    try:
+        # bpo-38377: On Linux, creating a semaphore is the current user
+        # does not have the permission to create a file in /dev/shm.
+        # Create a semaphore to check permissions.
+        synchronize.Lock(ctx=None)
+    except OSError as exc:
+        raise unittest.SkipTest(f"broken multiprocessing SemLock: {exc!r}")
index e7324d2e4811bb31c0b53c4f65200e830b3108dc..ef9d6fc48e9f88af8db4d1a1ee50aba11ec17930 100644 (file)
@@ -2673,10 +2673,10 @@ class GetEventLoopTestsMixin:
     if sys.platform != 'win32':
 
         def test_get_event_loop_new_process(self):
-            # Issue bpo-32126: The multiprocessing module used by
+            # bpo-32126: The multiprocessing module used by
             # ProcessPoolExecutor is not functional when the
             # multiprocessing.synchronize module cannot be imported.
-            support.import_module('multiprocessing.synchronize')
+            support.skip_if_broken_multiprocessing_synchronize()
 
             async def main():
                 pool = concurrent.futures.ProcessPoolExecutor()
index 0ed75e6098a80030498651fd9e561a68fa0454db..7da967ea6ced576d42ea168a0dac0c810f60c840 100644 (file)
@@ -4,7 +4,7 @@ from test.support import threading_helper
 # Skip tests if _multiprocessing wasn't built.
 support.import_module('_multiprocessing')
 # Skip tests if sem_open implementation is broken.
-support.import_module('multiprocessing.synchronize')
+support.skip_if_broken_multiprocessing_synchronize()
 
 from test.support import hashlib_helper
 from test.support.script_helper import assert_python_ok
index 275ce2e45f169cbd9b842d8604a99b85dc5789fd..e719d264a919148591499bb945d7001db2e7c5e2 100644 (file)
@@ -3630,9 +3630,9 @@ if hasattr(logging.handlers, 'QueueListener'):
 
         @patch.object(logging.handlers.QueueListener, 'handle')
         def test_handle_called_with_mp_queue(self, mock_handle):
-            # Issue 28668: The multiprocessing (mp) module is not functional
+            # bpo-28668: The multiprocessing (mp) module is not functional
             # when the mp.synchronize module cannot be imported.
-            support.import_module('multiprocessing.synchronize')
+            support.skip_if_broken_multiprocessing_synchronize()
             for i in range(self.repeat):
                 log_queue = multiprocessing.Queue()
                 self.setup_and_log(log_queue, '%s_%s' % (self.id(), i))
@@ -3656,9 +3656,9 @@ if hasattr(logging.handlers, 'QueueListener'):
             indicates that messages were not registered on the queue until
             _after_ the QueueListener stopped.
             """
-            # Issue 28668: The multiprocessing (mp) module is not functional
+            # bpo-28668: The multiprocessing (mp) module is not functional
             # when the mp.synchronize module cannot be imported.
-            support.import_module('multiprocessing.synchronize')
+            support.skip_if_broken_multiprocessing_synchronize()
             for i in range(self.repeat):
                 queue = multiprocessing.Queue()
                 self.setup_and_log(queue, '%s_%s' %(self.id(), i))
index b6abfcc7e283d5e53225ffc9dbbe6b7bff822841..be1ff10e03a55a3bf8d3b09b1f1e6162cee8b7d0 100644 (file)
@@ -23,7 +23,7 @@ import multiprocessing
 AVAILABLE_START_METHODS = set(multiprocessing.get_all_start_methods())
 
 # Issue #22332: Skip tests if sem_open implementation is broken.
-support.import_module('multiprocessing.synchronize')
+support.skip_if_broken_multiprocessing_synchronize()
 
 verbose = support.verbose
 
index ef6d7bd5ad7da0b6b43869c794a6cfcda55fea62..d3191ed7b9955b2b2e2ef3937d0b4cd22d29eb49 100644 (file)
@@ -16,7 +16,8 @@ import sys
 import tempfile
 from test.support import (captured_stdout, captured_stderr, requires_zlib,
                           can_symlink, EnvironmentVarGuard, rmtree,
-                          import_module)
+                          import_module,
+                          skip_if_broken_multiprocessing_synchronize)
 import unittest
 import venv
 from unittest.mock import patch
@@ -357,10 +358,11 @@ class BasicTest(BaseTest):
         """
         Test that the multiprocessing is able to spawn.
         """
-        # Issue bpo-36342: Instantiation of a Pool object imports the
+        # bpo-36342: Instantiation of a Pool object imports the
         # multiprocessing.synchronize module. Skip the test if this module
         # cannot be imported.
-        import_module('multiprocessing.synchronize')
+        skip_if_broken_multiprocessing_synchronize()
+
         rmtree(self.env_dir)
         self.run_with_capture(venv.create, self.env_dir)
         envpy = os.path.join(os.path.realpath(self.env_dir),
diff --git a/Misc/NEWS.d/next/Tests/2020-06-17-18-00-21.bpo-38377.jfg4TH.rst b/Misc/NEWS.d/next/Tests/2020-06-17-18-00-21.bpo-38377.jfg4TH.rst
new file mode 100644 (file)
index 0000000..11a3076
--- /dev/null
@@ -0,0 +1,4 @@
+On Linux, skip tests using multiprocessing if the current user cannot create
+a file in ``/dev/shm/`` directory. Add the
+:func:`~test.support.skip_if_broken_multiprocessing_synchronize` function to
+the :mod:`test.support` module.