diff options
author | 2024-02-12 20:04:53 -0800 | |
---|---|---|
committer | 2024-02-21 07:27:30 -0800 | |
commit | 69fbd8f9f76df32d9bc72510e5d9348eb8f059bc (patch) | |
tree | 38b99a1affc12a1f5f97b355b77c25489c9c8e5b | |
parent | anydbm: Pickle support for multiprocessing spawn (diff) | |
download | portage-69fbd8f9f76df32d9bc72510e5d9348eb8f059bc.tar.gz portage-69fbd8f9f76df32d9bc72510e5d9348eb8f059bc.tar.bz2 portage-69fbd8f9f76df32d9bc72510e5d9348eb8f059bc.zip |
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@gentoo.org>
-rw-r--r-- | lib/_emerge/EbuildMetadataPhase.py | 34 | ||||
-rw-r--r-- | lib/_emerge/SubProcess.py | 5 |
2 files changed, 38 insertions, 1 deletions
diff --git a/lib/_emerge/EbuildMetadataPhase.py b/lib/_emerge/EbuildMetadataPhase.py index f4f685e81..249086f8a 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 029bbc3f4..057e0adc2 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. |