Use an instance of multiprocessing.Pipe to propagate mtimedb["ldpath"] from the MergeProcess child process to the parent process. This fixes env_update calls to avoid unnecessary regeneration of ld.so.cache in cases where mtimedb["ldpath"] has not changed since the last call to env_update.
Bug: https://bugs.gentoo.org/836375 --- lib/portage/dbapi/_MergeProcess.py | 18 ++++++++++++++++++ lib/portage/dbapi/vartree.py | 10 ++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/portage/dbapi/_MergeProcess.py b/lib/portage/dbapi/_MergeProcess.py index db3f3b105..667a5bf20 100644 --- a/lib/portage/dbapi/_MergeProcess.py +++ b/lib/portage/dbapi/_MergeProcess.py @@ -2,6 +2,7 @@ # Distributed under the terms of the GNU General Public License v2 import io +import multiprocessing import platform import fcntl @@ -38,6 +39,7 @@ class MergeProcess(ForkProcess): "_dblink", "_elog_keys", "_locked_vdb", + "_mtime_reader", ) def _start(self): @@ -113,6 +115,15 @@ class MergeProcess(ForkProcess): self._elog_reader_fd = None return False + def _mtime_handler(self): + try: + mtimes = self._mtime_reader.recv() + except EOFError: + pass + else: + self.prev_mtimes.clear() + self.prev_mtimes.update(mtimes) + def _spawn(self, args, fd_pipes, **kwargs): """ Extend the superclass _spawn method to perform some pre-fork and @@ -127,6 +138,11 @@ class MergeProcess(ForkProcess): fcntl.fcntl(elog_reader_fd, fcntl.F_GETFL) | os.O_NONBLOCK, ) + mtime_reader, mtime_writer = multiprocessing.Pipe(duplex=False) + fd_pipes[mtime_writer.fileno()] = mtime_writer.fileno() + self.scheduler.add_reader(mtime_reader.fileno(), self._mtime_handler) + self._mtime_reader = mtime_reader + blockers = None if self.blockers is not None: # Query blockers in the main process, since closing @@ -142,6 +158,7 @@ class MergeProcess(ForkProcess): vartree=self.vartree, blockers=blockers, pipe=elog_writer_fd, + mtime_pipe=mtime_writer, ) fd_pipes[elog_writer_fd] = elog_writer_fd self.scheduler.add_reader(elog_reader_fd, self._elog_output_handler) @@ -160,6 +177,7 @@ class MergeProcess(ForkProcess): self._elog_reader_fd = elog_reader_fd pids = super(MergeProcess, self)._spawn(args, fd_pipes, **kwargs) os.close(elog_writer_fd) + mtime_writer.close() self._buf = "" self._elog_keys = set() # Discard messages which will be collected by the subprocess, diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py index 602913862..a95d60691 100644 --- a/lib/portage/dbapi/vartree.py +++ b/lib/portage/dbapi/vartree.py @@ -1806,6 +1806,7 @@ class dblink: blockers=None, scheduler=None, pipe=None, + mtime_pipe=None, ): """ Creates a DBlink object for a given CPV. @@ -1862,6 +1863,7 @@ class dblink: self._device_path_map = {} self._hardlink_merge_map = {} self._hash_key = (self._eroot, self.mycpv) + self._mtime_pipe = mtime_pipe self._protect_obj = None self._pipe = pipe self._postinst_failure = False @@ -2618,6 +2620,7 @@ class dblink: writemsg_level=self._display_merge, vardbapi=self.vartree.dbapi, ) + self._send_mtimes(ldpath_mtimes) unmerge_with_replacement = preserve_paths is not None if not unmerge_with_replacement: @@ -4243,6 +4246,12 @@ class dblink: def _emerge_log(self, msg): emergelog(False, msg) + def _send_mtimes(self, mtimes): + if self._mtime_pipe is None: + return + + self._mtime_pipe.send(mtimes) + def treewalk( self, srcroot, @@ -5274,6 +5283,7 @@ class dblink: writemsg_level=self._display_merge, vardbapi=self.vartree.dbapi, ) + self._send_mtimes(prev_mtimes) # For gcc upgrades, preserved libs have to be removed after the # the library path has been updated. -- 2.35.1