mirror of
https://github.com/python/cpython.git
synced 2026-04-14 07:41:00 +00:00
gh-143706: Fix sys.argv not set during multiprocessing forkserver __main__ preload (#143717)
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.
This commit is contained in:
parent
d5882c5b70
commit
298d5440eb
4 changed files with 52 additions and 1 deletions
|
|
@ -152,6 +152,8 @@ def ensure_running(self):
|
|||
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')
|
||||
|
|
@ -197,7 +199,7 @@ def ensure_running(self):
|
|||
#
|
||||
|
||||
def main(listener_fd, alive_r, preload, main_path=None, sys_path=None,
|
||||
*, authkey_r=None):
|
||||
*, sys_argv=None, authkey_r=None):
|
||||
"""Run forkserver."""
|
||||
if authkey_r is not None:
|
||||
try:
|
||||
|
|
@ -209,6 +211,8 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None,
|
|||
authkey = b''
|
||||
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -7086,6 +7086,26 @@ def test_preload_main(self):
|
|||
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
|
||||
#
|
||||
|
|
|
|||
22
Lib/test/mp_preload_sysargv.py
Normal file
22
Lib/test/mp_preload_sysargv.py
Normal file
|
|
@ -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()
|
||||
|
|
@ -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!
|
||||
Loading…
Add table
Add a link
Reference in a new issue