* [gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/, lib/portage/package/ebuild/, ...
@ 2024-02-21 16:00 Zac Medico
0 siblings, 0 replies; only message in thread
From: Zac Medico @ 2024-02-21 16:00 UTC (permalink / raw
To: gentoo-commits
commit: 18cdb6331a66c1cc92f296b1aaf0538f63586875
Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Tue Feb 13 08:44:50 2024 +0000
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Feb 21 15:27:31 2024 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=18cdb633
EbuildPhase: async_check_locale
Change config.environ() check_locale calls to async_check_locale
calls in the EbuildPhase _async_start method in order to eliminate
synchronous waiting for child processes in the main event loop
thread.
Bug: https://bugs.gentoo.org/923841
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
lib/_emerge/EbuildMetadataPhase.py | 4 ++++
lib/_emerge/EbuildPhase.py | 28 ++++++++++++++++++++++++++-
lib/portage/package/ebuild/config.py | 26 +++++++++++--------------
lib/portage/util/futures/_asyncio/__init__.py | 9 +++++++++
lib/portage/util/locale.py | 28 ++++++++++++++++++---------
5 files changed, 70 insertions(+), 25 deletions(-)
diff --git a/lib/_emerge/EbuildMetadataPhase.py b/lib/_emerge/EbuildMetadataPhase.py
index fc64d84c94..54177840c7 100644
--- a/lib/_emerge/EbuildMetadataPhase.py
+++ b/lib/_emerge/EbuildMetadataPhase.py
@@ -8,6 +8,7 @@ import portage
portage.proxy.lazyimport.lazyimport(
globals(),
+ "_emerge.EbuildPhase:_setup_locale",
"portage.package.ebuild._metadata_invalid:eapi_invalid",
)
from portage import os
@@ -83,6 +84,9 @@ class EbuildMetadataPhase(SubProcess):
settings.setcpv(self.cpv)
settings.configdict["pkg"]["EAPI"] = parsed_eapi
+ # This requires above setcpv and EAPI setup.
+ await _setup_locale(self.settings)
+
debug = settings.get("PORTAGE_DEBUG") == "1"
master_fd = None
slave_fd = None
diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py
index 3b366f39c7..b472803438 100644
--- a/lib/_emerge/EbuildPhase.py
+++ b/lib/_emerge/EbuildPhase.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
import functools
@@ -24,6 +24,7 @@ from portage.package.ebuild.prepare_build_dirs import (
_prepare_fake_distdir,
_prepare_fake_filesdir,
)
+from portage.eapi import _get_eapi_attrs
from portage.util import writemsg, ensure_dirs
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
from portage.util._async.BuildLogger import BuildLogger
@@ -54,12 +55,34 @@ portage.proxy.lazyimport.lazyimport(
+ "_post_src_install_write_metadata,"
+ "_preinst_bsdflags",
"portage.util.futures.unix_events:_set_nonblocking",
+ "portage.util.locale:async_check_locale,split_LC_ALL",
)
from portage import os
from portage import _encodings
from portage import _unicode_encode
+async def _setup_locale(settings):
+ eapi_attrs = _get_eapi_attrs(settings["EAPI"])
+ if eapi_attrs.posixish_locale:
+ split_LC_ALL(settings)
+ settings["LC_COLLATE"] = "C"
+ # check_locale() returns None when check can not be executed.
+ if await async_check_locale(silent=True, env=settings.environ()) is False:
+ # try another locale
+ for l in ("C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "C"):
+ settings["LC_CTYPE"] = l
+ if await async_check_locale(silent=True, env=settings.environ()):
+ # TODO: output the following only once
+ # writemsg(
+ # _("!!! LC_CTYPE unsupported, using %s instead\n")
+ # % self.settings["LC_CTYPE"]
+ # )
+ break
+ else:
+ raise AssertionError("C locale did not pass the test!")
+
+
class EbuildPhase(CompositeTask):
__slots__ = ("actionmap", "fd_pipes", "phase", "settings") + ("_ebuild_lock",)
@@ -95,6 +118,9 @@ class EbuildPhase(CompositeTask):
self._start_task(AsyncTaskFuture(future=future), self._async_start_exit)
async def _async_start(self):
+
+ await _setup_locale(self.settings)
+
need_builddir = self.phase not in EbuildProcess._phases_without_builddir
if need_builddir:
diff --git a/lib/portage/package/ebuild/config.py b/lib/portage/package/ebuild/config.py
index c89354cbf7..bafdc55a08 100644
--- a/lib/portage/package/ebuild/config.py
+++ b/lib/portage/package/ebuild/config.py
@@ -29,7 +29,6 @@ portage.proxy.lazyimport.lazyimport(
"portage.dbapi.vartree:vartree",
"portage.package.ebuild.doebuild:_phase_func_map",
"portage.util.compression_probe:_compressors",
- "portage.util.locale:check_locale,split_LC_ALL",
)
from portage import bsd_chflags, load_mod, os, selinux, _unicode_decode
from portage.const import (
@@ -3371,20 +3370,17 @@ class config:
mydict["EBUILD_PHASE_FUNC"] = phase_func
if eapi_attrs.posixish_locale:
- split_LC_ALL(mydict)
- mydict["LC_COLLATE"] = "C"
- # check_locale() returns None when check can not be executed.
- if check_locale(silent=True, env=mydict) is False:
- # try another locale
- for l in ("C.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", "C"):
- mydict["LC_CTYPE"] = l
- if check_locale(silent=True, env=mydict):
- # TODO: output the following only once
- # writemsg(_("!!! LC_CTYPE unsupported, using %s instead\n")
- # % mydict["LC_CTYPE"])
- break
- else:
- raise AssertionError("C locale did not pass the test!")
+ if mydict.get("LC_ALL"):
+ # Sometimes this method is called for processes
+ # that are not ebuild phases, so only raise
+ # AssertionError for actual ebuild phases.
+ if phase and phase not in ("clean", "cleanrm", "fetch"):
+ raise AssertionError(
+ f"LC_ALL={mydict['LC_ALL']} for posixish locale. It seems that split_LC_ALL was not called for phase {phase}?"
+ )
+ elif "LC_ALL" in mydict:
+ # Delete placeholder from split_LC_ALL.
+ del mydict["LC_ALL"]
if not eapi_attrs.exports_PORTDIR:
mydict.pop("PORTDIR", None)
diff --git a/lib/portage/util/futures/_asyncio/__init__.py b/lib/portage/util/futures/_asyncio/__init__.py
index b6481c281e..22241f335d 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -16,6 +16,7 @@ __all__ = (
"set_child_watcher",
"get_event_loop_policy",
"set_event_loop_policy",
+ "run",
"shield",
"sleep",
"Task",
@@ -109,6 +110,14 @@ def set_child_watcher(watcher):
return get_event_loop_policy().set_child_watcher(watcher)
+# Emulate run since it's the preferred python API.
+def run(coro):
+ return _safe_loop().run_until_complete(coro)
+
+
+run.__doc__ = _real_asyncio.run.__doc__
+
+
def create_subprocess_exec(*args, **kwargs):
"""
Create a subprocess.
diff --git a/lib/portage/util/locale.py b/lib/portage/util/locale.py
index b5da8d949b..b6a41e7655 100644
--- a/lib/portage/util/locale.py
+++ b/lib/portage/util/locale.py
@@ -17,6 +17,7 @@ import traceback
import portage
from portage.util import _unicode_decode, writemsg_level
from portage.util._ctypes import find_library, LoadLibrary
+from portage.util.futures import asyncio
locale_categories = (
@@ -121,7 +122,10 @@ def check_locale(silent=False, env=None):
warning and returns False if it is not. Returns None if the check
can not be executed due to platform limitations.
"""
+ return asyncio.run(async_check_locale(silent=silent, env=env))
+
+async def async_check_locale(silent=False, env=None):
if env is not None:
for v in ("LC_ALL", "LC_CTYPE", "LANG"):
if v in env:
@@ -135,20 +139,17 @@ def check_locale(silent=False, env=None):
except KeyError:
pass
- # TODO: Make async version of check_locale and call it from
- # EbuildPhase instead of config.environ(), since it's bad to
- # synchronously wait for the process in the main event loop
- # thread where config.environ() tends to be called.
proc = multiprocessing.Process(
target=_set_and_check_locale,
args=(silent, env, None if env is None else portage._native_string(mylocale)),
)
proc.start()
- proc.join()
+ proc = portage.process.MultiprocessingProcess(proc)
+ await proc.wait()
pyret = None
- if proc.exitcode >= 0:
- ret = proc.exitcode
+ if proc.returncode >= 0:
+ ret = proc.returncode
if ret != 2:
pyret = ret == 0
@@ -157,13 +158,22 @@ def check_locale(silent=False, env=None):
return pyret
+async_check_locale.__doc__ = check_locale.__doc__
+async_check_locale.__doc__ += """
+ This function is a coroutine.
+"""
+
+
def split_LC_ALL(env):
"""
Replace LC_ALL with split-up LC_* variables if it is defined.
Works on the passed environment (or settings instance).
"""
lc_all = env.get("LC_ALL")
- if lc_all is not None:
+ if lc_all:
for c in locale_categories:
env[c] = lc_all
- del env["LC_ALL"]
+ # Set empty so that config.reset() can restore LC_ALL state,
+ # since del can permanently delete variables which are not
+ # stored in the config's backupenv.
+ env["LC_ALL"] = ""
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2024-02-21 16:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-21 16:00 [gentoo-commits] proj/portage:master commit in: lib/portage/util/futures/_asyncio/, lib/portage/package/ebuild/, Zac Medico
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox