Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Lib/multiprocessing/forkserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None):
spawn.import_main_path(main_path)
finally:
del process.current_process()._inheriting
if sys_path is not None:
sys.path[:] = sys_path
Comment thread
gpshead marked this conversation as resolved.
Outdated
for modname in preload:
try:
__import__(modname)
Expand Down
57 changes: 57 additions & 0 deletions Lib/test/test_multiprocessing_forkserver/test_forkserver_main.py
Comment thread
gpshead marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
import sys
import unittest
from unittest import mock

from multiprocessing import forkserver


class TestForkserverMain(unittest.TestCase):

def setUp(self):
self._orig_sys_path = list(sys.path)

def tearDown(self):
sys.path[:] = self._orig_sys_path

@mock.patch("multiprocessing.process.current_process")
@mock.patch("multiprocessing.spawn.import_main_path")
@mock.patch("multiprocessing.util._close_stdin")
def test_preload_kwargs(
self,
mock_close_stdin,
mock_import_main_path,
mock_current_process,
):
# Very much a whitebox test of the first stanza of main before
# we start diddling with file descriptors and pipes.
mock_close_stdin.side_effect = RuntimeError("stop test")
self.assertNotIn(
"colorsys",
sys.modules.keys(),
msg="Thie test requires a module that has not yet been imported.",
)

with self.assertRaisesRegex(RuntimeError, "stop test"):
forkserver.main(None, None, ["sys", "colorsys"])
mock_current_process.assert_not_called()
mock_import_main_path.assert_not_called()
self.assertIn("colorsys", sys.modules.keys())
self.assertEqual(sys.path, self._orig_sys_path) # unmodified

del sys.modules["colorsys"] # unimport
fake_path = os.path.dirname(__file__)
with self.assertRaisesRegex(RuntimeError, "stop test"):
forkserver.main(None, None, ["sys", "colorsys"], sys_path=[fake_path])
self.assertEqual(
sys.path, [fake_path], msg="sys.path should have been overridden"
)
self.assertNotIn(
"colorsys",
sys.modules.keys(),
msg="import of colorsys should have failed with unusual sys.path",
)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Fixed the :mod:`multiprocessing` ``"forkserver"`` start method forkserver
process was to correctly inherit the parent's :data:`sys.path` during the
importing of :func:`multiprocessing.set_forkserver_preload` modules in the
same manner as :data:`sys.path` is configured when executing work items in
the worker processes.

This bug could cause some forkserver module preloading to silently fail to
be preloaded, leading to a performance degration in child processes due to
additional repeated work. It could also have led to a side effect of ``""``
still being in :data:`sys.path` during forkserver preload imports instead of
the absolute path of the directory that workers see.