Skip to content

Commit 4ba182a

Browse files
committed
Do not export PMS variables
Instead of passing PMS variables as part of the process environment, we pass them via a file that is later sourced by the ebuild's bash. Since, for example, A is usually the greatest contributor to the process environment, removing it from the process environment significantly avoids running into MAX_ARG_STRLEN when spawning a new child process. This means that A and other PMS variables are no longer exported in the ebuild and hence unavaiable to child processes. However, A is mostly used as part of the default_src_unpack function and there A does not need to be exported. This started as a change that only unexported A, but was later extended to most PMS variables as suggested by ulm in https://bugs.gentoo.org/721088#c23. Thanks to Zac Medico for helpful input on this change, and to Eli Schwartz for suggesting that (bash) helpers should simply source the environment file introduced by this change. Closes: https://bugs.gentoo.org/721088 Signed-off-by: Florian Schmaus <[email protected]>
1 parent 6f958be commit 4ba182a

File tree

4 files changed

+98
-2
lines changed

4 files changed

+98
-2
lines changed

bin/isolated-functions.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ if ___eapi_has_version_functions; then
88
source "${PORTAGE_BIN_PATH}/eapi7-ver-funcs.sh" || exit 1
99
fi
1010

11+
if [[ -v PORTAGE_EBUILD_EXTRA_SOURCE ]]; then
12+
source "${PORTAGE_EBUILD_EXTRA_SOURCE}" || exit 1
13+
# We delierbately do not unset PORTABE_EBUILD_EXTRA_SOURCE, so
14+
# that it keeps being exported in the environment of this
15+
# processes and its child processeses.
16+
fi
17+
1118
# We need this next line for "die" and "assert". It expands
1219
# It _must_ preceed all the calls to die and assert.
1320
shopt -s expand_aliases

lib/portage/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
"digest",
182182
"distcc",
183183
"distlocks",
184+
"dont-export-pms-vars",
184185
"downgrade-backup",
185186
"ebuild-locks",
186187
"fail-clean",

lib/portage/eapi.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2010-2021 Gentoo Authors
1+
# Copyright 2010-2024 Gentoo Authors
22
# Distributed under the terms of the GNU General Public License v2
33

44
import collections
@@ -48,6 +48,10 @@ def eapi_supports_prefix(eapi: str) -> bool:
4848
return _get_eapi_attrs(eapi).prefix
4949

5050

51+
def eapi_exports_pms_vars(eapi: str) -> bool:
52+
return _get_eapi_attrs(eapi).exports_pms_vars
53+
54+
5155
def eapi_exports_AA(eapi: str) -> bool:
5256
return _get_eapi_attrs(eapi).exports_AA
5357

@@ -157,6 +161,7 @@ def eapi_has_sysroot(eapi: str) -> bool:
157161
"exports_ECLASSDIR",
158162
"exports_KV",
159163
"exports_merge_type",
164+
"exports_pms_vars",
160165
"exports_PORTDIR",
161166
"exports_replace_vars",
162167
"feature_flag_test",
@@ -198,6 +203,7 @@ class Eapi:
198203
"6",
199204
"7",
200205
"8",
206+
"9",
201207
)
202208

203209
_eapi_val: int = -1
@@ -236,6 +242,7 @@ def _get_eapi_attrs(eapi_str: Optional[str]) -> _eapi_attrs:
236242
exports_ECLASSDIR=False,
237243
exports_KV=False,
238244
exports_merge_type=True,
245+
exports_pms_vars=True,
239246
exports_PORTDIR=True,
240247
exports_replace_vars=True,
241248
feature_flag_test=False,
@@ -275,6 +282,7 @@ def _get_eapi_attrs(eapi_str: Optional[str]) -> _eapi_attrs:
275282
exports_ECLASSDIR=eapi <= Eapi("6"),
276283
exports_KV=eapi <= Eapi("3"),
277284
exports_merge_type=eapi >= Eapi("4"),
285+
exports_pms_vars=eapi <= Eapi("8"),
278286
exports_PORTDIR=eapi <= Eapi("6"),
279287
exports_replace_vars=eapi >= Eapi("4"),
280288
feature_flag_test=False,

lib/portage/package/ebuild/doebuild.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
from portage.eapi import (
8585
eapi_exports_KV,
8686
eapi_exports_merge_type,
87+
eapi_exports_pms_vars,
8788
eapi_exports_replace_vars,
8889
eapi_has_required_use,
8990
eapi_has_src_prepare_and_src_configure,
@@ -189,6 +190,57 @@
189190
"RESTRICT",
190191
)
191192

193+
# The following is a set of PMS § 11.1 and § 7.4 without
194+
# - TMPDIR
195+
# - HOME
196+
# because these variables are often assumed to be exported and
197+
# therefore consumed by child processes.
198+
_unexported_pms_vars = frozenset(
199+
# fmt: off
200+
[
201+
# PMS § 11.1 Defined Variables
202+
"P", # NOT-EXPORTED: tendency to break Makefiles when exported
203+
"PF",
204+
"PN",
205+
"CATEGORY",
206+
"PV",
207+
"PR",
208+
"PVR",
209+
"A", # NOT-EXPORTED: largest contributor to process environment when exported
210+
"AA", # NOT-EXPORTED: unused after EAPI 4
211+
"FILESDIR",
212+
"DISTDIR",
213+
"WORKDIR",
214+
"S",
215+
"PORTDIR",
216+
"ECLASSDIR",
217+
"ROOT",
218+
"EROOT",
219+
"SYSROOT",
220+
"ESYSROOT",
221+
"BROOT",
222+
"T",
223+
# "TMPDIR", # EXPORTED: often assumed to be exported and available to child processes
224+
# "HOME", # EXPORTED: often assumed to be exported and available to child processes
225+
"EPREFIX",
226+
"D", # NOT-EXPORTED: tendency to break Makefiles when exported
227+
"ED",
228+
"DESTTREE",
229+
"INSDESTTREE",
230+
"EBUILD_PHASE",
231+
"EBUILD_PHASE_FUNC",
232+
"KV",
233+
"MERGE_TYPE",
234+
"REPLACING_VERSIONS",
235+
"REPLACED_BY_VERSION",
236+
# PMS 7.4 Magic Ebuild-defined Variables
237+
"ECLASS",
238+
"INHERITED",
239+
"DEFINED_PHASES",
240+
]
241+
# fmt: on
242+
)
243+
192244

193245
def _doebuild_spawn(phase, settings, actionmap=None, **kwargs):
194246
"""
@@ -2133,9 +2185,37 @@ def spawn(
21332185
logname_backup = mysettings.configdict["env"].get("LOGNAME")
21342186
mysettings.configdict["env"]["LOGNAME"] = logname
21352187

2188+
eapi = mysettings["EAPI"]
2189+
2190+
unexported_env_vars = None
2191+
if "dont-export-pms-vars" in mysettings.features or not eapi_exports_pms_vars(eapi):
2192+
unexported_env_vars = _unexported_pms_vars
2193+
2194+
if unexported_env_vars:
2195+
orig_env = mysettings.environ()
2196+
# Copy since we are potentially removing keys from the dict.
2197+
env = orig_env.copy()
2198+
2199+
t = env["T"]
2200+
if not os.path.isdir(t):
2201+
os.makedirs(t)
2202+
2203+
ebuildExtraSource = os.path.join(t, ".portage-ebuild-extra-source")
2204+
with open(ebuildExtraSource, mode="w") as f:
2205+
for var_name in unexported_env_vars:
2206+
var_value = orig_env.get(var_name)
2207+
if var_value is None:
2208+
continue
2209+
f.write(f"{var_name}='{var_value}'\n")
2210+
del env[var_name]
2211+
2212+
env["PORTAGE_EBUILD_EXTRA_SOURCE"] = str(ebuildExtraSource)
2213+
else:
2214+
env = mysettings.environ()
2215+
21362216
try:
21372217
if keywords.get("returnpid") or keywords.get("returnproc"):
2138-
return spawn_func(mystring, env=mysettings.environ(), **keywords)
2218+
return spawn_func(mystring, env=env, **keywords)
21392219

21402220
proc = EbuildSpawnProcess(
21412221
background=False,

0 commit comments

Comments
 (0)