commit: 9040f400a65f6739918269c0e4d7ebf626fac811 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Thu Nov 13 03:19:20 2025 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Thu Nov 13 06:36:41 2025 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=9040f400
_prepare_self_update: update sys.path for forkserver or spawn For multiprocessing forkserver and spawn start methods, sys.path is inherited from the main process, so it needs to include portage._pym_path where _prepare_self_update has created a backup of modules for the running version of portage. Bug: https://bugs.gentoo.org/965976 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> lib/portage/package/ebuild/doebuild.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lib/portage/package/ebuild/doebuild.py b/lib/portage/package/ebuild/doebuild.py index 53d70a9391..e83dfc0291 100644 --- a/lib/portage/package/ebuild/doebuild.py +++ b/lib/portage/package/ebuild/doebuild.py @@ -15,6 +15,7 @@ import platform import pwd import re import shlex +import signal import stat import subprocess import sys @@ -3422,6 +3423,38 @@ def _prepare_self_update(settings): for dir_path in (base_path_tmp, portage._bin_path, portage._pym_path): os.chmod(dir_path, 0o755) + # Update sys.path used to unpickle child process arguments for + # multiprocessing forkserver and spawn start methods (bug 965976). + sys.path.insert(0, portage._pym_path) + + if multiprocessing.get_start_method() == "forkserver": + + def _get_forkserver_pid(): + try: + return multiprocessing.forkserver._forkserver._forkserver_pid + except AttributeError: + return None + + forkserver_pid = _get_forkserver_pid() + if not isinstance(forkserver_pid, int): + # force forkserver launch + portage.process.spawn(["true"]) + forkserver_pid = _get_forkserver_pid() + + if not isinstance(forkserver_pid, int): + writemsg( + "!!! Failed to locate forkserver pid for sys.path update\n", + noiselevel=-1, + ) + + # If a forkserver was successfully launched then it + # inherited our sys.path update and there is no need + # to kill it. + else: + # Kill forkserver in order to force a sys.path update, + # and a new forkserver will launch on demand. + os.kill(forkserver_pid, signal.SIGTERM) + def _handle_self_update(settings, vardb): if installation.TYPE != installation.TYPES.SYSTEM:
