aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2024-02-12 20:04:53 -0800
committerZac Medico <zmedico@gentoo.org>2024-02-21 07:27:30 -0800
commit69fbd8f9f76df32d9bc72510e5d9348eb8f059bc (patch)
tree38b99a1affc12a1f5f97b355b77c25489c9c8e5b
parentanydbm: Pickle support for multiprocessing spawn (diff)
downloadportage-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.py34
-rw-r--r--lib/_emerge/SubProcess.py5
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.