]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-143706: Fix sys.argv not set during multiprocessing forkserver `__main__...
authorGregory P. Smith <68491+gpshead@users.noreply.github.com>
Wed, 14 Jan 2026 02:09:05 +0000 (18:09 -0800)
committerGitHub <noreply@github.com>
Wed, 14 Jan 2026 02:09:05 +0000 (18:09 -0800)
The forkserver was not passing sys.argv to its main() function, causing
sys.argv to be empty during `__main__` module import in child processes. This
fixes a non-obvious regression inadvertently introduced by the gh-126631 main
preloading fix.

(cherry picked from commit 298d5440eb83f2dfd5651bac86d1592ec358d54c)

Lib/multiprocessing/forkserver.py
Lib/test/_test_multiprocessing.py
Lib/test/mp_preload_sysargv.py [new file with mode: 0644]
Misc/NEWS.d/next/Library/2026-01-12-07-17-38.gh-issue-143706.sysArgv.rst [new file with mode: 0644]

index e243442e7a15bd80c7a424d12c50df65936e02f6..009da9b40bbccd60a391150af00b6269e1c39204 100644 (file)
@@ -134,6 +134,8 @@ class ForkServer(object):
                     main_kws['sys_path'] = data['sys_path']
                 if 'init_main_from_path' in data:
                     main_kws['main_path'] = data['init_main_from_path']
+                if 'sys_argv' in data:
+                    main_kws['sys_argv'] = data['sys_argv']
 
             with socket.socket(socket.AF_UNIX) as listener:
                 address = connection.arbitrary_address('AF_UNIX')
@@ -166,9 +168,12 @@ class ForkServer(object):
 #
 #
 
-def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
+def main(listener_fd, alive_r, preload, main_path=None, sys_path=None,
+         *, sys_argv=None):
     '''Run forkserver.'''
     if preload:
+        if sys_argv is not None:
+            sys.argv[:] = sys_argv
         if sys_path is not None:
             sys.path[:] = sys_path
         if '__main__' in preload and main_path is not None:
index 550463ca2636cba5677086f3eea20ee20ea2c18f..35a6f0830d472fd6e76d7be5142d9f3eeb8d53ba 100644 (file)
@@ -6584,6 +6584,26 @@ class MiscTestCase(unittest.TestCase):
         out = out.decode().split("\n")
         self.assertEqual(out, ['__main__', '__mp_main__', 'f', 'f', ''])
 
+    def test_preload_main_sys_argv(self):
+        # gh-143706: Check that sys.argv is set before __main__ is pre-loaded
+        if multiprocessing.get_start_method() != "forkserver":
+            self.skipTest("forkserver specific test")
+
+        name = os.path.join(os.path.dirname(__file__), 'mp_preload_sysargv.py')
+        _, out, err = test.support.script_helper.assert_python_ok(
+            name, 'foo', 'bar')
+        self.assertEqual(err, b'')
+
+        out = out.decode().split("\n")
+        expected_argv = "['foo', 'bar']"
+        self.assertEqual(out, [
+            f"module:{expected_argv}",
+            f"fun:{expected_argv}",
+            f"module:{expected_argv}",
+            f"fun:{expected_argv}",
+            '',
+        ])
+
 #
 # Mixins
 #
diff --git a/Lib/test/mp_preload_sysargv.py b/Lib/test/mp_preload_sysargv.py
new file mode 100644 (file)
index 0000000..5ad38cd
--- /dev/null
@@ -0,0 +1,22 @@
+# gh-143706: Test that sys.argv is correctly set during main module import
+# when using forkserver with __main__ preloading.
+
+import multiprocessing
+import sys
+
+# This will be printed during module import - sys.argv should be correct here
+print(f"module:{sys.argv[1:]}")
+
+def fun():
+    # This will be printed when the function is called
+    print(f"fun:{sys.argv[1:]}")
+
+if __name__ == "__main__":
+    ctx = multiprocessing.get_context("forkserver")
+    ctx.set_forkserver_preload(['__main__'])
+
+    fun()
+
+    p = ctx.Process(target=fun)
+    p.start()
+    p.join()
diff --git a/Misc/NEWS.d/next/Library/2026-01-12-07-17-38.gh-issue-143706.sysArgv.rst b/Misc/NEWS.d/next/Library/2026-01-12-07-17-38.gh-issue-143706.sysArgv.rst
new file mode 100644 (file)
index 0000000..5bdefbb
--- /dev/null
@@ -0,0 +1,5 @@
+Fix :mod:`multiprocessing` forkserver so that :data:`sys.argv` is correctly
+set before ``__main__`` is preloaded. Previously, :data:`sys.argv` was empty
+during main module import in forkserver child processes. This fixes a
+regression introduced in 3.13.8 and 3.14.1. Root caused by Aaron Wieczorek,
+test provided by Thomas Watson, thanks!