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


Reply via email to