1 |
Asynchronously lock the build directory. The asynchronous lock delays |
2 |
creation of the pid, and it's possible for the _wait method to be called |
3 |
before the pid is available. Therefore, AbstractEbuildProcess._wait() |
4 |
must wait for the pid to become available before it can call the |
5 |
SpawnProcess._wait() method. |
6 |
|
7 |
Bug: https://bugs.gentoo.org/614112 |
8 |
--- |
9 |
pym/_emerge/AbstractEbuildProcess.py | 30 ++++++++++++++++++++++++++---- |
10 |
1 file changed, 26 insertions(+), 4 deletions(-) |
11 |
|
12 |
diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py |
13 |
index 2aa0c4a35..d481e6046 100644 |
14 |
--- a/pym/_emerge/AbstractEbuildProcess.py |
15 |
+++ b/pym/_emerge/AbstractEbuildProcess.py |
16 |
@@ -25,7 +25,7 @@ class AbstractEbuildProcess(SpawnProcess): |
17 |
|
18 |
__slots__ = ('phase', 'settings',) + \ |
19 |
('_build_dir', '_build_dir_unlock', '_ipc_daemon', |
20 |
- '_exit_command', '_exit_timeout_id') |
21 |
+ '_exit_command', '_exit_timeout_id', '_start_future') |
22 |
|
23 |
_phases_without_builddir = ('clean', 'cleanrm', 'depend', 'help',) |
24 |
_phases_interactive_whitelist = ('config',) |
25 |
@@ -130,15 +130,19 @@ class AbstractEbuildProcess(SpawnProcess): |
26 |
# since we're not displaying to a terminal anyway. |
27 |
self.settings['NOCOLOR'] = 'true' |
28 |
|
29 |
+ start_ipc_daemon = False |
30 |
if self._enable_ipc_daemon: |
31 |
self.settings.pop('PORTAGE_EBUILD_EXIT_FILE', None) |
32 |
if self.phase not in self._phases_without_builddir: |
33 |
+ start_ipc_daemon = True |
34 |
if 'PORTAGE_BUILDDIR_LOCKED' not in self.settings: |
35 |
self._build_dir = EbuildBuildDir( |
36 |
scheduler=self.scheduler, settings=self.settings) |
37 |
- self._build_dir.lock() |
38 |
- self.settings['PORTAGE_IPC_DAEMON'] = "1" |
39 |
- self._start_ipc_daemon() |
40 |
+ self._start_future = self._build_dir.async_lock() |
41 |
+ self._start_future.add_done_callback( |
42 |
+ functools.partial(self._start_post_builddir_lock, |
43 |
+ start_ipc_daemon=start_ipc_daemon)) |
44 |
+ return |
45 |
else: |
46 |
self.settings.pop('PORTAGE_IPC_DAEMON', None) |
47 |
else: |
48 |
@@ -159,6 +163,19 @@ class AbstractEbuildProcess(SpawnProcess): |
49 |
else: |
50 |
self.settings.pop('PORTAGE_EBUILD_EXIT_FILE', None) |
51 |
|
52 |
+ self._start_post_builddir_lock(start_ipc_daemon=start_ipc_daemon) |
53 |
+ |
54 |
+ def _start_post_builddir_lock(self, lock_future=None, start_ipc_daemon=False): |
55 |
+ if lock_future is not None: |
56 |
+ if lock_future is not self._start_future: |
57 |
+ raise AssertionError('lock_future is not self._start_future') |
58 |
+ self._start_future = None |
59 |
+ lock_future.result() |
60 |
+ |
61 |
+ if start_ipc_daemon: |
62 |
+ self.settings['PORTAGE_IPC_DAEMON'] = "1" |
63 |
+ self._start_ipc_daemon() |
64 |
+ |
65 |
if self.fd_pipes is None: |
66 |
self.fd_pipes = {} |
67 |
null_fd = None |
68 |
@@ -375,6 +392,11 @@ class AbstractEbuildProcess(SpawnProcess): |
69 |
Execution of the failsafe code will automatically become a fatal |
70 |
error at the same time as event loop recursion is disabled. |
71 |
""" |
72 |
+ # SpawnProcess._wait() requires the pid, so wait here for the |
73 |
+ # pid to become available. |
74 |
+ while self._start_future is not None: |
75 |
+ self.scheduler.run_until_complete(self._start_future) |
76 |
+ |
77 |
SpawnProcess._wait(self) |
78 |
|
79 |
if self._build_dir is not None: |
80 |
-- |
81 |
2.13.6 |