commit:     6f9a10d38259dd61b948837e193b047464791845
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Mon Mar  4 05:31:08 2024 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Mon Mar  4 05:33:44 2024 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=6f9a10d3

SpawnProcess: Optimize away null input for create_pipe=False

When create_pipe=False support was added in commit e8b31c86eaed,
a null input file descriptor was used for PipeLogger and BuildLogger
instances. Optimize this away, eliminating the unnecessary loggers.

Fixes: e8b31c86eaed ("ForkProcess: Prevent redundant pipe and set_term_size 
recursion")
Bug: https://bugs.gentoo.org/916566
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/_emerge/SpawnProcess.py            | 51 +++++++++++++++++-----------------
 lib/portage/util/_async/ForkProcess.py |  7 ++---
 2 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/lib/_emerge/SpawnProcess.py b/lib/_emerge/SpawnProcess.py
index 9fc12c42e5..513a7b2fe4 100644
--- a/lib/_emerge/SpawnProcess.py
+++ b/lib/_emerge/SpawnProcess.py
@@ -79,10 +79,7 @@ class SpawnProcess(SubProcess):
                 # SpawnProcess will have created a pipe earlier, so it
                 # would be redundant to do it here (it could also trigger
                 # spawn recursion via set_term_size as in bug 923750).
-                # Use /dev/null for master_fd, triggering early return
-                # of _main, followed by _async_waitpid.
-                # TODO: Optimize away the need for master_fd here.
-                master_fd = os.open(os.devnull, os.O_RDONLY)
+                master_fd = None
                 slave_fd = None
                 can_log = False
 
@@ -166,23 +163,27 @@ class SpawnProcess(SubProcess):
         self._registered = True
 
     def _start_main_task(self, pr, log_file_path=None, stdout_fd=None):
-        build_logger = BuildLogger(
-            env=self.env,
-            log_path=log_file_path,
-            log_filter_file=self.log_filter_file,
-            scheduler=self.scheduler,
-        )
-        build_logger.start()
-
-        pipe_logger = PipeLogger(
-            background=self.background,
-            scheduler=self.scheduler,
-            input_fd=pr,
-            log_file_path=build_logger.stdin,
-            stdout_fd=stdout_fd,
-        )
-
-        pipe_logger.start()
+        if pr is None:
+            build_logger = None
+            pipe_logger = None
+        else:
+            build_logger = BuildLogger(
+                env=self.env,
+                log_path=log_file_path,
+                log_filter_file=self.log_filter_file,
+                scheduler=self.scheduler,
+            )
+            build_logger.start()
+
+            pipe_logger = PipeLogger(
+                background=self.background,
+                scheduler=self.scheduler,
+                input_fd=pr,
+                log_file_path=build_logger.stdin,
+                stdout_fd=stdout_fd,
+            )
+
+            pipe_logger.start()
 
         self._main_task_cancel = functools.partial(
             self._main_cancel, build_logger, pipe_logger
@@ -198,18 +199,18 @@ class SpawnProcess(SubProcess):
             await self._pty_ready
             self._pty_ready = None
         try:
-            if pipe_logger.poll() is None:
+            if pipe_logger is not None and pipe_logger.poll() is None:
                 await pipe_logger.async_wait()
-            if build_logger.poll() is None:
+            if build_logger is not None and build_logger.poll() is None:
                 await build_logger.async_wait()
         except asyncio.CancelledError:
             self._main_cancel(build_logger, pipe_logger)
             raise
 
     def _main_cancel(self, build_logger, pipe_logger):
-        if pipe_logger.poll() is None:
+        if pipe_logger is not None and pipe_logger.poll() is None:
             pipe_logger.cancel()
-        if build_logger.poll() is None:
+        if build_logger is not None and build_logger.poll() is None:
             build_logger.cancel()
 
     def _main_exit(self, main_task):

diff --git a/lib/portage/util/_async/ForkProcess.py 
b/lib/portage/util/_async/ForkProcess.py
index ebcbd94107..e6cfdefb88 100644
--- a/lib/portage/util/_async/ForkProcess.py
+++ b/lib/portage/util/_async/ForkProcess.py
@@ -91,11 +91,8 @@ class ForkProcess(SpawnProcess):
                     # When called via process.spawn, SpawnProcess
                     # will have created a pipe earlier, so it would be
                     # redundant to do it here (it could also trigger spawn
-                    # recursion via set_term_size as in bug 923750). Use
-                    # /dev/null for master_fd, triggering early return
-                    # of _main, followed by _async_waitpid.
-                    # TODO: Optimize away the need for master_fd here.
-                    master_fd = os.open(os.devnull, os.O_RDONLY)
+                    # recursion via set_term_size as in bug 923750).
+                    master_fd = None
                     slave_fd = None
 
                 self._files = self._files_dict(connection=connection, 
slave_fd=slave_fd)

Reply via email to