commit: 69fbd8f9f76df32d9bc72510e5d9348eb8f059bc Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Tue Feb 13 04:04:53 2024 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Wed Feb 21 15:27:30 2024 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=69fbd8f9
EbuildMetadataPhase: Add deallocate_config future Use a deallocate_config future to release self.settings when it is no longer needed. It's necessary to manage concurrency since commit c95fc64abf96 because mutation of self.settings is no longer limited to the EbuildMetadataPhase _start method, where exclusive access was guaranteed within the main thread. Add support to the isAlive() method to detect when the EbuildMetadataPhase has started but the pid is not yet available (due to async_check_locale usage from commit c95fc64abf96). This can be used to check if an EbuildMetadataPhase instance has been successfully started so that it can be relied upon to set the result of the deallocate_config future. Bug: https://bugs.gentoo.org/924319 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> lib/_emerge/EbuildMetadataPhase.py | 34 ++++++++++++++++++++++++++++++++++ lib/_emerge/SubProcess.py | 5 ++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/_emerge/EbuildMetadataPhase.py b/lib/_emerge/EbuildMetadataPhase.py index f4f685e81c..249086f8af 100644 --- a/lib/_emerge/EbuildMetadataPhase.py +++ b/lib/_emerge/EbuildMetadataPhase.py @@ -14,6 +14,7 @@ from portage import os from portage import _encodings from portage import _unicode_decode from portage import _unicode_encode +from portage.util.futures import asyncio import fcntl @@ -33,6 +34,7 @@ class EbuildMetadataPhase(SubProcess): "portdb", "repo_path", "settings", + "deallocate_config", "write_auxdb", ) + ( "_eapi", @@ -127,6 +129,15 @@ class EbuildMetadataPhase(SubProcess): returnproc=True, ) settings.pop("PORTAGE_PIPE_FD", None) + # At this point we can return settings to the caller + # since we never use it for anything more than an + # eapi_invalid call after this, and eapi_invalid is + # insensitive to concurrent modifications. + if ( + self.deallocate_config is not None + and not self.deallocate_config.cancelled() + ): + self.deallocate_config.set_result(settings) os.close(slave_fd) null_input.close() @@ -139,6 +150,29 @@ class EbuildMetadataPhase(SubProcess): self._proc = retval + asyncio.ensure_future( + self._async_start(), loop=self.scheduler + ).add_done_callback(self._async_start_done) + + async def _async_start(self): + # Call async check_locale here for bug 923841, but code + # also needs to migrate from _start to here, including + # the self.deallocate_config set_result call. + pass + + def _async_start_done(self, future): + future.cancelled() or future.result() + if not self._was_cancelled() and future.cancelled(): + self.cancel() + self._was_cancelled() + + if self.deallocate_config is not None and not self.deallocate_config.done(): + self.deallocate_config.set_result(self.settings) + + if self.returncode is not None: + self._unregister() + self.wait() + def _output_handler(self): while True: buf = self._read_buf(self._files.ebuild) diff --git a/lib/_emerge/SubProcess.py b/lib/_emerge/SubProcess.py index 029bbc3f44..057e0adc24 100644 --- a/lib/_emerge/SubProcess.py +++ b/lib/_emerge/SubProcess.py @@ -18,9 +18,12 @@ class SubProcess(AbstractPollTask): # we've sent a kill signal to our subprocess. _cancel_timeout = 1 # seconds + def isAlive(self): + return (self._registered or self.pid is not None) and self.returncode is None + @property def pid(self): - return self._proc.pid + return None if self._proc is None else self._proc.pid def _poll(self): # Simply rely on _async_waitpid_cb to set the returncode.
