aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2024-02-11 18:10:52 -0800
committerZac Medico <zmedico@gentoo.org>2024-02-12 05:57:42 -0800
commit67663e586320347e604727aef006bfe027bcd470 (patch)
tree8e7afade046e3519d89c044f9872b6c7b367d94c
parentprocess._exec: Use _start_fork for os.fork() error handling (diff)
downloadportage-67663e586320347e604727aef006bfe027bcd470.tar.gz
portage-67663e586320347e604727aef006bfe027bcd470.tar.bz2
portage-67663e586320347e604727aef006bfe027bcd470.zip
EbuildBuild: Execute EbuildFetchonly in subprocess
Execute EbuildFetchonly in a subprocess since it needs to run the event loop itself (even for pretend mode since it may need to fetch mirror layouts as reported in bug 702154). Also remove obsolete loop.is_running() case in doebuild related to bug 601252, since it will fail if a mirror layout file needs to be fetched, so we should just assume that the event loop is not running. Set fetched = 2 for listonly (pretend) mode in the fetch function so that EbuildFetchonly will properly report success for this mode. Pass ebuild_path to EbuildFetchonly, and also remove setcpv call from EbuildFetchonly since it's called earlier in EbuildBuild. Bug: https://bugs.gentoo.org/924287 Signed-off-by: Zac Medico <zmedico@gentoo.org>
-rw-r--r--lib/_emerge/EbuildBuild.py39
-rw-r--r--lib/_emerge/EbuildFetchonly.py10
-rw-r--r--lib/portage/package/ebuild/doebuild.py30
-rw-r--r--lib/portage/package/ebuild/fetch.py1
4 files changed, 33 insertions, 47 deletions
diff --git a/lib/_emerge/EbuildBuild.py b/lib/_emerge/EbuildBuild.py
index 81cbfdc08..d4a4c6dac 100644
--- a/lib/_emerge/EbuildBuild.py
+++ b/lib/_emerge/EbuildBuild.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
import functools
@@ -22,6 +22,7 @@ from portage.package.ebuild.digestcheck import digestcheck
from portage.package.ebuild.doebuild import _check_temp_dir
from portage.package.ebuild._spawn_nofetch import SpawnNofetchWithoutBuilddir
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
+from portage.util.futures.executor.fork import ForkExecutor
from portage.util.path import first_existing
@@ -152,29 +153,25 @@ class EbuildBuild(CompositeTask):
if opts.fetchonly:
if opts.pretend:
fetcher = EbuildFetchonly(
+ ebuild_path=self._ebuild_path,
fetch_all=opts.fetch_all_uri,
pkg=pkg,
pretend=opts.pretend,
settings=settings,
)
- retval = fetcher.execute()
- if retval == os.EX_OK:
- self._current_task = None
- self.returncode = os.EX_OK
- self._async_wait()
- else:
- # For pretend mode, the convention it to execute
- # pkg_nofetch and return a successful exitcode.
- self._start_task(
- SpawnNofetchWithoutBuilddir(
- background=self.background,
- portdb=self.pkg.root_config.trees[self._tree].dbapi,
- ebuild_path=self._ebuild_path,
- scheduler=self.scheduler,
- settings=self.settings,
+ # Execute EbuildFetchonly in a subprocess since it needs to
+ # run the event loop itself (even for pretend mode since it
+ # may need to fetch mirror layouts as reported in bug 702154).
+ self._start_task(
+ AsyncTaskFuture(
+ background=self.background,
+ scheduler=self.scheduler,
+ future=self.scheduler.run_in_executor(
+ ForkExecutor(loop=self.scheduler), fetcher.execute
),
- self._default_final_exit,
- )
+ ),
+ self._fetchonly_exit,
+ )
return
quiet_setting = settings.get("PORTAGE_QUIET", False)
@@ -241,8 +238,12 @@ class EbuildBuild(CompositeTask):
self._start_task(pre_clean_phase, self._pre_clean_exit)
def _fetchonly_exit(self, fetcher):
+ if not fetcher.cancelled and isinstance(fetcher, AsyncTaskFuture):
+ # Set returncode from EbuildFetchonly.execute() result, since
+ # it can fail if it can't resolve a mirror for a file.
+ fetcher.returncode = fetcher.future.result()
self._final_exit(fetcher)
- if self.returncode != os.EX_OK:
+ if not self.cancelled and self.returncode != os.EX_OK:
self.returncode = None
portdb = self.pkg.root_config.trees[self._tree].dbapi
self._start_task(
diff --git a/lib/_emerge/EbuildFetchonly.py b/lib/_emerge/EbuildFetchonly.py
index e887dd858..c806122be 100644
--- a/lib/_emerge/EbuildFetchonly.py
+++ b/lib/_emerge/EbuildFetchonly.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2012 Gentoo Foundation
+# Copyright 1999-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
import portage
@@ -8,20 +8,16 @@ from portage.util.SlotObject import SlotObject
class EbuildFetchonly(SlotObject):
- __slots__ = ("fetch_all", "pkg", "pretend", "settings")
+ __slots__ = ("ebuild_path", "fetch_all", "pkg", "pretend", "settings")
def execute(self):
settings = self.settings
pkg = self.pkg
portdb = pkg.root_config.trees["porttree"].dbapi
- ebuild_path = portdb.findname(pkg.cpv, myrepo=pkg.repo)
- if ebuild_path is None:
- raise AssertionError(f"ebuild not found for '{pkg.cpv}'")
- settings.setcpv(pkg)
debug = settings.get("PORTAGE_DEBUG") == "1"
rval = portage.doebuild(
- ebuild_path,
+ self.ebuild_path,
"fetch",
settings=settings,
debug=debug,
diff --git a/lib/portage/package/ebuild/doebuild.py b/lib/portage/package/ebuild/doebuild.py
index 1c89af5ac..4cf155e03 100644
--- a/lib/portage/package/ebuild/doebuild.py
+++ b/lib/portage/package/ebuild/doebuild.py
@@ -1334,32 +1334,20 @@ def doebuild(
dist_digests = mf.getTypeDigests("DIST")
loop = asyncio._safe_loop()
- if loop.is_running():
- # Called by EbuildFetchonly for emerge --pretend --fetchonly.
- success = fetch(
+ success = loop.run_until_complete(
+ loop.run_in_executor(
+ ForkExecutor(loop=loop),
+ _fetch_subprocess,
fetchme,
mysettings,
- listonly=listonly,
- fetchonly=fetchonly,
- allow_missing_digests=False,
- digests=dist_digests,
- )
- else:
- success = loop.run_until_complete(
- loop.run_in_executor(
- ForkExecutor(loop=loop),
- _fetch_subprocess,
- fetchme,
- mysettings,
- listonly,
- dist_digests,
- fetchonly,
- )
+ listonly,
+ dist_digests,
+ fetchonly,
)
+ )
if not success:
# Since listonly mode is called by emerge --pretend in an
- # asynchronous context, spawn_nofetch would trigger event loop
- # recursion here, therefore delegate execution of pkg_nofetch
+ # asynchronous context, execution of pkg_nofetch is delegated
# to the caller (bug 657360).
if not listonly:
spawn_nofetch(
diff --git a/lib/portage/package/ebuild/fetch.py b/lib/portage/package/ebuild/fetch.py
index 5f970fe62..bfa0c2b27 100644
--- a/lib/portage/package/ebuild/fetch.py
+++ b/lib/portage/package/ebuild/fetch.py
@@ -1562,6 +1562,7 @@ def fetch(
tried_locations.add(loc)
if listonly:
writemsg_stdout(loc + " ", noiselevel=-1)
+ fetched = 2
continue
# allow different fetchcommands per protocol
protocol = loc[0 : loc.find("://")]