]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-77377: Ensure multiprocessing SemLock is valid for spawn-based Process...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 23 Aug 2023 23:44:07 +0000 (16:44 -0700)
committerGitHub <noreply@github.com>
Wed, 23 Aug 2023 23:44:07 +0000 (01:44 +0200)
gh-77377: Ensure multiprocessing SemLock is valid for spawn-based Process before serializing it (GH-107275)

Ensure multiprocessing SemLock is valid for spawn Process before serializing it.

Creating a multiprocessing SemLock with a fork context, and then trying to pass it to a spawn-created Process, would segfault if not detected early.

---------

(cherry picked from commit 1700d34d314f5304a7a75363bda295a8c15c371f)

Co-authored-by: albanD <desmaison.alban@gmail.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Antoine Pitrou <pitrou@free.fr>
Lib/multiprocessing/synchronize.py
Lib/test/_test_multiprocessing.py
Misc/NEWS.d/next/Core and Builtins/2023-07-25-22-35-35.gh-issue-77377.EHAbXx.rst [new file with mode: 0644]

index 42624b543601a16d47d01441578225dcaedc579f..2328d33212308256bf9d2d2e8f2d562263157350 100644 (file)
@@ -50,8 +50,8 @@ class SemLock(object):
     def __init__(self, kind, value, maxvalue, *, ctx):
         if ctx is None:
             ctx = context._default_context.get_context()
-        name = ctx.get_start_method()
-        unlink_now = sys.platform == 'win32' or name == 'fork'
+        self.is_fork_ctx = ctx.get_start_method() == 'fork'
+        unlink_now = sys.platform == 'win32' or self.is_fork_ctx
         for i in range(100):
             try:
                 sl = self._semlock = _multiprocessing.SemLock(
@@ -103,6 +103,11 @@ class SemLock(object):
         if sys.platform == 'win32':
             h = context.get_spawning_popen().duplicate_for_child(sl.handle)
         else:
+            if self.is_fork_ctx:
+                raise RuntimeError('A SemLock created in a fork context is being '
+                                   'shared with a process in a spawn context. This is '
+                                   'not supported. Please use the same context to create '
+                                   'multiprocessing objects and Process.')
             h = sl.handle
         return (h, sl.kind, sl.maxvalue, sl.name)
 
index 4afbe172a1eefab516e2a255d3c3b7fea5fd1b7a..1afb8735a2f55d62933b8e46f05284cf61442bb4 100644 (file)
@@ -5383,6 +5383,28 @@ class TestStartMethod(unittest.TestCase):
             print(err)
             self.fail("failed spawning forkserver or grandchild")
 
+    @unittest.skipIf(sys.platform == "win32",
+                     "Only Spawn on windows so no risk of mixing")
+    @only_run_in_spawn_testsuite("avoids redundant testing.")
+    def test_mixed_startmethod(self):
+        # Fork-based locks cannot be used with spawned process
+        for process_method in ["spawn", "forkserver"]:
+            queue = multiprocessing.get_context("fork").Queue()
+            process_ctx = multiprocessing.get_context(process_method)
+            p = process_ctx.Process(target=close_queue, args=(queue,))
+            err_msg = "A SemLock created in a fork"
+            with self.assertRaisesRegex(RuntimeError, err_msg):
+                p.start()
+
+        # non-fork-based locks can be used with all other start methods
+        for queue_method in ["spawn", "forkserver"]:
+            for process_method in multiprocessing.get_all_start_methods():
+                queue = multiprocessing.get_context(queue_method).Queue()
+                process_ctx = multiprocessing.get_context(process_method)
+                p = process_ctx.Process(target=close_queue, args=(queue,))
+                p.start()
+                p.join()
+
 
 @unittest.skipIf(sys.platform == "win32",
                  "test semantics don't make sense on Windows")
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-25-22-35-35.gh-issue-77377.EHAbXx.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-25-22-35-35.gh-issue-77377.EHAbXx.rst
new file mode 100644 (file)
index 0000000..194851d
--- /dev/null
@@ -0,0 +1 @@
+Ensure that multiprocessing synchronization objects created in a fork context are not sent to a different process created in a spawn context. This changes a segfault into an actionable RuntimeError in the parent process.