From d9ec4a20541adcce5c2624e8d209e77b1fce4613 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Tue, 2 Apr 2024 22:28:30 +0200 Subject: [PATCH] PoC: Do not export A Instead of passing A as part of the process environment, we pass it via a file. Since A is usually the greatest contributor to the process environment, removing it from the process environment significantly helps running into MAX_ARG_STRLEN when spawning a new child process. This means that A is now unexported in the ebuild. However, A is mostly used as part of the default_src_unpack function. And there A does not need to be exported. Proof-of-concept for https://bugs.gentoo.org/721088 Bug: https://bugs.gentoo.org/721088 Signed-off-by: Florian Schmaus --- bin/ebuild.sh | 6 +++++- lib/portage/package/ebuild/doebuild.py | 30 +++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 8b1e0861a8..7ffb91e5a3 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 1999-2021 Gentoo Authors +# Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 # Prevent aliases from causing portage to act inappropriately. @@ -10,6 +10,10 @@ unalias -a unset BASH_COMPAT declare -F ___in_portage_iuse >/dev/null && export -n -f ___in_portage_iuse +if [[ -v PORTAGE_EBUILD_EXTRA_SOURCE ]]; then + source "${PORTAGE_EBUILD_EXTRA_SOURCE}" || exit 1 +fi + source "${PORTAGE_BIN_PATH}/isolated-functions.sh" || exit 1 # Set up the bash version compatibility level. This does not disable diff --git a/lib/portage/package/ebuild/doebuild.py b/lib/portage/package/ebuild/doebuild.py index c7fa1d1e06..d34a14630c 100644 --- a/lib/portage/package/ebuild/doebuild.py +++ b/lib/portage/package/ebuild/doebuild.py @@ -2131,9 +2131,37 @@ def spawn( logname_backup = mysettings.configdict["env"].get("LOGNAME") mysettings.configdict["env"]["LOGNAME"] = logname + eapi = mysettings["EAPI"] + + # TODO: Move into eapi.py + def eapi_does_not_export_a(eapi): + return eapi == "9" + + dont_export_a = "dont-export-a" in mysettings.features or eapi_does_not_export_a( + eapi + ) + + if dont_export_a: + orig_env = mysettings.environ() + # Copy since we are potentially removing keys from the dict. + env = orig_env.copy() + t = env["T"] + if os.path.isdir(t): + ebuildExtraSource = os.path.join(t, "portage-ebuild-extra-source") + with open(ebuildExtraSource, mode="w") as f: + for name, value in orig_env.items(): + if name != "A": + continue + f.write(f"{name}='{value}'\n") + del env[name] + + env["PORTAGE_EBUILD_EXTRA_SOURCE"] = str(ebuildExtraSource) + else: + env = mysettings.environ() + try: if keywords.get("returnpid") or keywords.get("returnproc"): - return spawn_func(mystring, env=mysettings.environ(), **keywords) + return spawn_func(mystring, env=env, **keywords) proc = EbuildSpawnProcess( background=False,