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 2/6] AbstractEbuildProcess: use async_lock (bug 614112)
Date: Sat, 21 Apr 2018 08:28:36
Message-Id: 20180421082440.32706-3-zmedico@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH 0/6] EbuildBuildDir: add async_lock method (bug 614112) by Zac Medico
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