1 |
In order to avoid event loop recursion, convert the |
2 |
_BinpkgFetcherProcess.lock() method to an async_lock |
3 |
method for use by BinpkgFetcher. |
4 |
|
5 |
Bug: https://bugs.gentoo.org/614110 |
6 |
--- |
7 |
pym/_emerge/BinpkgFetcher.py | 53 +++++++++++++++++++++++++++----------------- |
8 |
1 file changed, 33 insertions(+), 20 deletions(-) |
9 |
|
10 |
diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py |
11 |
index 5ca7a45cf..2bbc0a26f 100644 |
12 |
--- a/pym/_emerge/BinpkgFetcher.py |
13 |
+++ b/pym/_emerge/BinpkgFetcher.py |
14 |
@@ -32,11 +32,24 @@ class BinpkgFetcher(CompositeTask): |
15 |
pkg.cpv) + ".partial" |
16 |
|
17 |
def _start(self): |
18 |
- self._start_task( |
19 |
- _BinpkgFetcherProcess(background=self.background, |
20 |
- logfile=self.logfile, pkg=self.pkg, pkg_path=self.pkg_path, |
21 |
- pretend=self.pretend, scheduler=self.scheduler), |
22 |
- self._fetcher_exit) |
23 |
+ fetcher = _BinpkgFetcherProcess(background=self.background, |
24 |
+ logfile=self.logfile, pkg=self.pkg, pkg_path=self.pkg_path, |
25 |
+ pretend=self.pretend, scheduler=self.scheduler) |
26 |
+ |
27 |
+ if not self.pretend: |
28 |
+ portage.util.ensure_dirs(os.path.dirname(self.pkg_path)) |
29 |
+ if "distlocks" in self.pkg.root_config.settings.features: |
30 |
+ self._start_task( |
31 |
+ AsyncTaskFuture(future=fetcher.async_lock()), |
32 |
+ functools.partial(self._start_locked, fetcher)) |
33 |
+ return |
34 |
+ |
35 |
+ self._start_task(fetcher, self._fetcher_exit) |
36 |
+ |
37 |
+ def _start_locked(self, fetcher, lock_task): |
38 |
+ self._assert_current(lock_task) |
39 |
+ lock_task.future.result() |
40 |
+ self._start_task(fetcher, self._fetcher_exit) |
41 |
|
42 |
def _fetcher_exit(self, fetcher): |
43 |
self._assert_current(fetcher) |
44 |
@@ -68,13 +81,8 @@ class _BinpkgFetcherProcess(SpawnProcess): |
45 |
pretend = self.pretend |
46 |
bintree = pkg.root_config.trees["bintree"] |
47 |
settings = bintree.settings |
48 |
- use_locks = "distlocks" in settings.features |
49 |
pkg_path = self.pkg_path |
50 |
|
51 |
- if not pretend: |
52 |
- portage.util.ensure_dirs(os.path.dirname(pkg_path)) |
53 |
- if use_locks: |
54 |
- self.lock() |
55 |
exists = os.path.exists(pkg_path) |
56 |
resume = exists and os.path.basename(pkg_path) in bintree.invalids |
57 |
if not (pretend or resume): |
58 |
@@ -184,7 +192,7 @@ class _BinpkgFetcherProcess(SpawnProcess): |
59 |
except OSError: |
60 |
pass |
61 |
|
62 |
- def lock(self): |
63 |
+ def async_lock(self): |
64 |
""" |
65 |
This raises an AlreadyLocked exception if lock() is called |
66 |
while a lock is already held. In order to avoid this, call |
67 |
@@ -194,17 +202,22 @@ class _BinpkgFetcherProcess(SpawnProcess): |
68 |
if self._lock_obj is not None: |
69 |
raise self.AlreadyLocked((self._lock_obj,)) |
70 |
|
71 |
- async_lock = AsynchronousLock(path=self.pkg_path, |
72 |
- scheduler=self.scheduler) |
73 |
- async_lock.start() |
74 |
+ result = self.scheduler.create_future() |
75 |
|
76 |
- if async_lock.wait() != os.EX_OK: |
77 |
- # TODO: Use CompositeTask for better handling, like in EbuildPhase. |
78 |
- raise AssertionError("AsynchronousLock failed with returncode %s" \ |
79 |
- % (async_lock.returncode,)) |
80 |
+ def acquired_lock(async_lock): |
81 |
+ if async_lock.wait() == os.EX_OK: |
82 |
+ self.locked = True |
83 |
+ result.set_result(None) |
84 |
+ else: |
85 |
+ result.set_exception(AssertionError( |
86 |
+ "AsynchronousLock failed with returncode %s" |
87 |
+ % (async_lock.returncode,))) |
88 |
|
89 |
- self._lock_obj = async_lock |
90 |
- self.locked = True |
91 |
+ self._lock_obj = AsynchronousLock(path=self.pkg_path, |
92 |
+ scheduler=self.scheduler) |
93 |
+ self._lock_obj.addExitListener(acquired_lock) |
94 |
+ self._lock_obj.start() |
95 |
+ return result |
96 |
|
97 |
class AlreadyLocked(portage.exception.PortageException): |
98 |
pass |
99 |
-- |
100 |
2.13.6 |