commit:     9b711229ef913e8772e9a3a1cce744c87ee468cf
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Mon Nov 27 01:55:04 2023 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Tue Nov 28 22:47:53 2023 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=9b711229

Cancel prefetchers that have not started yet

Cancel prefetchers that have not started yet. This will cause the
parallel-fetch SequentialTaskQueue to simply discard them, and
a regular fetcher will be instantiated immediately. This prevents
errors when accessing the pkg_path attribute of BinpkgPrefetcher
instances that have not started yet.

Bug: https://bugs.gentoo.org/918636
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/_emerge/Binpkg.py        | 6 +++++-
 lib/_emerge/CompositeTask.py | 8 +++++++-
 lib/_emerge/EbuildBuild.py   | 4 ++++
 lib/_emerge/Scheduler.py     | 8 +++++++-
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/lib/_emerge/Binpkg.py b/lib/_emerge/Binpkg.py
index fac8722064..9b1036538a 100644
--- a/lib/_emerge/Binpkg.py
+++ b/lib/_emerge/Binpkg.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import functools
@@ -110,6 +110,10 @@ class Binpkg(CompositeTask):
         # use the scheduler and fetcher methods to
         # synchronize with the fetcher.
         prefetcher = self.prefetcher
+        if prefetcher is not None and not prefetcher.isAlive():
+            # Cancel it because it hasn't started yet.
+            prefetcher.cancel()
+            self.prefetcher = prefetcher = None
         if prefetcher is None:
             pass
         elif prefetcher.isAlive() and prefetcher.poll() is None:

diff --git a/lib/_emerge/CompositeTask.py b/lib/_emerge/CompositeTask.py
index a0203e71f3..50c1b8c5f3 100644
--- a/lib/_emerge/CompositeTask.py
+++ b/lib/_emerge/CompositeTask.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2018 Gentoo Foundation
+# Copyright 1999-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from _emerge.AsynchronousTask import AsynchronousTask
@@ -10,6 +10,12 @@ class CompositeTask(AsynchronousTask):
 
     _TASK_QUEUED = -1
 
+    def isAlive(self):
+        """
+        Returns True if started and returncode has not been set.
+        """
+        return self.returncode is None and self._current_task is not None
+
     def _cancel(self):
         if self._current_task is not None:
             if self._current_task is self._TASK_QUEUED:

diff --git a/lib/_emerge/EbuildBuild.py b/lib/_emerge/EbuildBuild.py
index 079a67ffbe..81cbfdc085 100644
--- a/lib/_emerge/EbuildBuild.py
+++ b/lib/_emerge/EbuildBuild.py
@@ -96,6 +96,10 @@ class EbuildBuild(CompositeTask):
             return
 
         prefetcher = self.prefetcher
+        if prefetcher is not None and not prefetcher.isAlive():
+            # Cancel it because it hasn't started yet.
+            prefetcher.cancel()
+            self.prefetcher = prefetcher = None
         if prefetcher is None:
             pass
         elif prefetcher.isAlive() and prefetcher.poll() is None:

diff --git a/lib/_emerge/Scheduler.py b/lib/_emerge/Scheduler.py
index e1179e0f13..66eca4c650 100644
--- a/lib/_emerge/Scheduler.py
+++ b/lib/_emerge/Scheduler.py
@@ -940,6 +940,10 @@ class Scheduler(PollScheduler):
                     # is consuming time here.
                     if bintree.isremote(x.cpv):
                         fetcher = self._get_prefetcher(x)
+                        if fetcher is not None and not fetcher.isAlive():
+                            # Cancel it because it hasn't started yet.
+                            fetcher.cancel()
+                            fetcher = None
                         if fetcher is None:
                             fetcher = BinpkgFetcher(pkg=x, scheduler=loop)
                             fetcher.start()
@@ -1963,7 +1967,9 @@ class Scheduler(PollScheduler):
             # CPython 2.7, so it may be possible for CPython to raise KeyError
             # here as well.
             prefetcher = None
-        if prefetcher is not None and not prefetcher.isAlive():
+        if prefetcher is not None and (
+            prefetcher.cancelled or not prefetcher.isAlive()
+        ):
             try:
                 self._task_queues.fetch._task_queue.remove(prefetcher)
             except ValueError:

Reply via email to