Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH 5/5] EbuildFetcher: add async_already_fetched method (bug 653810)
Date: Sun, 22 Apr 2018 22:33:31
Message-Id: 20180422223014.24341-6-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 0/5] EbuildFetcher._get_uri_map(): fix event loop recursion (bug 653810) by Zac Medico
1 Add an async_already_fetched method to replace the synchronous
2 already_fetched method, and use it to prevent event loop recursion.
3
4 Bug: https://bugs.gentoo.org/653810
5 ---
6 pym/_emerge/EbuildBuild.py | 8 +++++++-
7 pym/_emerge/EbuildFetcher.py | 30 ++++++++++++++++++++++++------
8 2 files changed, 31 insertions(+), 7 deletions(-)
9
10 diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py
11 index 9d4afd0ea..21c7f81ce 100644
12 --- a/pym/_emerge/EbuildBuild.py
13 +++ b/pym/_emerge/EbuildBuild.py
14 @@ -207,8 +207,14 @@ class EbuildBuild(CompositeTask):
15 logfile=self.settings.get('PORTAGE_LOG_FILE'),
16 pkg=self.pkg, scheduler=self.scheduler)
17
18 + self._start_task(AsyncTaskFuture(
19 + future=fetcher.async_already_fetched(self.settings)),
20 + functools.partial(self._start_fetch, fetcher))
21 +
22 + def _start_fetch(self, fetcher, already_fetched_task):
23 + self._assert_current(already_fetched_task)
24 try:
25 - already_fetched = fetcher.already_fetched(self.settings)
26 + already_fetched = already_fetched_task.future.result()
27 except portage.exception.InvalidDependString as e:
28 msg_lines = []
29 msg = "Fetch failed for '%s' due to invalid SRC_URI: %s" % \
30 diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py
31 index 8f6cc60fe..589eda85d 100644
32 --- a/pym/_emerge/EbuildFetcher.py
33 +++ b/pym/_emerge/EbuildFetcher.py
34 @@ -28,7 +28,7 @@ class EbuildFetcher(CompositeTask):
35 CompositeTask.__init__(self, **kwargs)
36 self._fetcher_proc = _EbuildFetcherProcess(**kwargs)
37
38 - def already_fetched(self, settings):
39 + def async_already_fetched(self, settings):
40 """
41 Returns True if all files already exist locally and have correct
42 digests, otherwise return False. When returning True, appropriate
43 @@ -38,7 +38,7 @@ class EbuildFetcher(CompositeTask):
44 such messages. This will raise InvalidDependString if SRC_URI is
45 invalid.
46 """
47 - return self._fetcher_proc.already_fetched(settings)
48 + return self._fetcher_proc.async_already_fetched(settings)
49
50 def _start(self):
51 self._start_task(
52 @@ -68,11 +68,29 @@ class _EbuildFetcherProcess(ForkProcess):
53 __slots__ = ("config_pool", "ebuild_path", "fetchonly", "fetchall",
54 "pkg", "prefetch", "_digests", "_manifest", "_settings", "_uri_map")
55
56 - def already_fetched(self, settings):
57 - uri_map = self.scheduler.run_until_complete(self._async_uri_map())
58 - if not uri_map:
59 - return True
60 + def async_already_fetched(self, settings):
61 + result = self.scheduler.create_future()
62 +
63 + def uri_map_done(uri_map_future):
64 + if uri_map_future.exception() is not None or result.cancelled():
65 + if not result.cancelled():
66 + result.set_exception(uri_map_future.exception())
67 + return
68 +
69 + uri_map = uri_map_future.result()
70 + if uri_map:
71 + result.set_result(
72 + self._check_already_fetched(settings, uri_map))
73 + else:
74 + result.set_result(True)
75 +
76 + uri_map_future = self._async_uri_map()
77 + result.add_done_callback(lambda result:
78 + aux_get_future.cancel() if result.cancelled() else None)
79 + uri_map_future.add_done_callback(uri_map_done)
80 + return result
81
82 + def _check_already_fetched(self, settings, uri_map):
83 digests = self._get_digests()
84 distdir = settings["DISTDIR"]
85 allow_missing = self._get_manifest().allow_missing
86 --
87 2.13.6