Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config.environ: delay export of A and AA (bug 720180) #552

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bin/eapi.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ ___eapi_has_S_WORKDIR_fallback() {

# VARIABLES

___eapi_exports_A() {
# https://bugs.gentoo.org/721088
true
}

___eapi_exports_AA() {
[[ ${1-${EAPI-0}} =~ ^(0|1|2|3)$ ]]
}

___eapi_has_prefix_variables() {
[[ ! ${1-${EAPI-0}} =~ ^(0|1|2)$ || " ${FEATURES} " == *" force-prefix "* ]]
}
Expand Down
34 changes: 34 additions & 0 deletions bin/isolated-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,39 @@ __bashpid() {
sh -c 'echo ${PPID}'
}

# @FUNCTION: ___eapi_vars_export
# @DESCRIPTION:
# Export variables for the current EAPI. Calls to this function should
# be delayed until the last moment, since exporting these variables
# may trigger E2BIG errors suring attempts to execute subprocesses.
___eapi_vars_export() {
source "${T}/environment.unexported" || die

if ___eapi_exports_A; then
export A
fi

if ___eapi_exports_AA; then
export AA
fi
}

# @FUNCTION: ___eapi_vars_unexport
# @DESCRIPTION:
# Unexport variables that were exported for the current EAPI. This
# function should be called after an ebuild phase, in order to unexport
# variables that may trigger E2BIG errors during attempts to execute
# subprocesses.
___eapi_vars_unexport() {
if ___eapi_exports_A; then
export -n A
fi

if ___eapi_exports_AA; then
export -n AA
fi
}

__helpers_die() {
if ___eapi_helpers_can_die && [[ ${PORTAGE_NONFATAL} != 1 ]]; then
die "$@"
Expand All @@ -122,6 +155,7 @@ die() {

set +x # tracing only produces useless noise here
local IFS=$' \t\n'
___eapi_vars_unexport

if ___eapi_die_can_respect_nonfatal && [[ $1 == -n ]]; then
shift
Expand Down
13 changes: 13 additions & 0 deletions bin/phase-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ __filter_readonly_variables() {
fi
fi

___eapi_vars_unexport
"${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}"/filter-bash-environment.py "${filtered_vars}" || die "filter-bash-environment.py failed"
}

Expand Down Expand Up @@ -212,6 +213,7 @@ __ebuild_phase() {

__ebuild_phase_with_hooks() {
local x phase_name=${1}
___eapi_vars_export
for x in {pre_,,post_}${phase_name} ; do
__ebuild_phase ${x}
done
Expand All @@ -223,6 +225,7 @@ __dyn_pretend() {
__vecho ">>> Remove '$PORTAGE_BUILDDIR/.pretended' to force pretend."
return 0
fi
___eapi_vars_export
__ebuild_phase pre_pkg_pretend
__ebuild_phase pkg_pretend
>> "$PORTAGE_BUILDDIR/.pretended" || \
Expand All @@ -236,6 +239,7 @@ __dyn_setup() {
__vecho ">>> Remove '$PORTAGE_BUILDDIR/.setuped' to force setup."
return 0
fi
___eapi_vars_export
__ebuild_phase pre_pkg_setup
__ebuild_phase pkg_setup
>> "$PORTAGE_BUILDDIR/.setuped" || \
Expand All @@ -252,6 +256,7 @@ __dyn_unpack() {
install -m${PORTAGE_WORKDIR_MODE:-0700} -d "${WORKDIR}" || die "Failed to create dir '${WORKDIR}'"
fi
cd "${WORKDIR}" || die "Directory change failed: \`cd '${WORKDIR}'\`"
___eapi_vars_export
__ebuild_phase pre_src_unpack
__vecho ">>> Unpacking source..."
__ebuild_phase src_unpack
Expand Down Expand Up @@ -387,6 +392,7 @@ __dyn_prepare() {

trap __abort_prepare SIGINT SIGQUIT

___eapi_vars_export
__ebuild_phase pre_src_prepare
__vecho ">>> Preparing source in $PWD ..."
__ebuild_phase src_prepare
Expand Down Expand Up @@ -424,6 +430,7 @@ __dyn_configure() {

trap __abort_configure SIGINT SIGQUIT

___eapi_vars_export
__ebuild_phase pre_src_configure

__vecho ">>> Configuring source in $PWD ..."
Expand Down Expand Up @@ -457,6 +464,7 @@ __dyn_compile() {

trap __abort_compile SIGINT SIGQUIT

___eapi_vars_export
__ebuild_phase pre_src_compile

__vecho ">>> Compiling source in $PWD ..."
Expand Down Expand Up @@ -503,6 +511,7 @@ __dyn_test() {
else
local save_sp=${SANDBOX_PREDICT}
addpredict /
___eapi_vars_export
__ebuild_phase pre_src_test

__vecho ">>> Test phase: ${CATEGORY}/${PF}"
Expand Down Expand Up @@ -556,6 +565,7 @@ __dyn_install() {
eval "[[ -n \$QA_PRESTRIPPED_${ARCH/-/_} ]] && \
export QA_PRESTRIPPED_${ARCH/-/_}"

___eapi_vars_export
__ebuild_phase pre_src_install

if ___eapi_has_prefix_variables; then
Expand Down Expand Up @@ -698,6 +708,7 @@ __dyn_install() {
--filter-path --filter-sandbox --allow-extra-vars > \
"${PORTAGE_BUILDDIR}"/build-info/environment
assert "__save_ebuild_env failed"
___eapi_vars_unexport
cd "${PORTAGE_BUILDDIR}"/build-info || die

${PORTAGE_BZIP2_COMMAND} -f9 environment
Expand Down Expand Up @@ -1096,11 +1107,13 @@ __ebuild_main() {
__save_ebuild_env | __filter_readonly_variables \
--filter-features > "$T/environment"
assert "__save_ebuild_env failed"
___eapi_vars_unexport
chgrp "${PORTAGE_GRPNAME:-portage}" "$T/environment"
chmod g+w "$T/environment"
fi
[[ -n $PORTAGE_EBUILD_EXIT_FILE ]] && > "$PORTAGE_EBUILD_EXIT_FILE"
if [[ -n $PORTAGE_IPC_DAEMON ]] ; then
___eapi_vars_unexport
[[ ! -s $SANDBOX_LOG ]]
"$PORTAGE_BIN_PATH"/ebuild-ipc exit $?
fi
Expand Down
10 changes: 9 additions & 1 deletion lib/portage/package/ebuild/_config/special_env_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
# user config variables
environ_whitelist += ["DOC_SYMLINKS_DIR", "INSTALL_MASK", "PKG_INSTALL_MASK"]

environ_whitelist += ["A", "AA", "CATEGORY", "P", "PF", "PN", "PR", "PV", "PVR"]
environ_whitelist += ["CATEGORY", "P", "PF", "PN", "PR", "PV", "PVR"]

# misc variables inherited from the calling environment
environ_whitelist += [
Expand Down Expand Up @@ -247,13 +247,21 @@

environ_whitelist_re = re.compile(r"^(CCACHE_|DISTCC_).*")

environ_unexported = frozenset(
[
"A",
"AA",
]
)

# Filter selected variables in the config.environ() method so that
# they don't needlessly propagate down into the ebuild environment.
environ_filter = []

# Exclude anything that could be extremely long here (like SRC_URI)
# since that could cause execve() calls to fail with E2BIG errors. For
# example, see bug #262647.
environ_filter.extend(environ_unexported)
environ_filter += [
"DEPEND",
"RDEPEND",
Expand Down
45 changes: 34 additions & 11 deletions lib/portage/package/ebuild/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import copy
from itertools import chain
import grp
import io
import logging
import platform
import pwd
Expand All @@ -31,7 +32,7 @@
"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 import bsd_chflags, load_mod, os, selinux, _encodings, _unicode_decode
from portage.const import (
CACHE_PATH,
DEPCACHE_PATH,
Expand Down Expand Up @@ -3218,17 +3219,43 @@ def environ(self):
eapi_attrs = _get_eapi_attrs(eapi)
phase = self.get("EBUILD_PHASE")
emerge_from = self.get("EMERGE_FROM")
temp_dir = None
filter_calling_env = False
if (
self.mycpv is not None
and not (emerge_from == "ebuild" and phase == "setup")
and "PORTAGE_BUILDDIR_LOCKED" in self
and phase not in ("clean", "cleanrm", "depend", "fetch")
):
temp_dir = self.get("T")
if temp_dir is not None and os.path.exists(
os.path.join(temp_dir, "environment")
):
filter_calling_env = True
temp_dir = self["T"]
# These variables will exported by ebuild.sh if appropriate
# for the current EAPI, but export is delayed since large
# values may trigger E2BIG errors during attempts to spawn
# subprocesses.
unexported = []
for key in special_env_vars.environ_unexported:
# Don't export AA for EAPIs that forbid it.
if key == "AA" and not eapi_exports_AA(eapi):
continue
value = self.get(key)
if value is not None:
unexported.append((key, value))

# Write this file even if it's empty, so that ebuild.sh can
# rely on its existence.
with io.open(
os.path.join(temp_dir, "environment.unexported"),
mode="wt",
encoding=_encodings["repo.content"],
) as f:
for key, value in unexported:
f.write('%s="%s"\n' % (key, value.replace('"', '\\"')))

if (
temp_dir is not None
and not (emerge_from == "ebuild" and phase == "setup")
and os.path.exists(os.path.join(temp_dir, "environment"))
):
filter_calling_env = True

environ_whitelist = self._environ_whitelist
for x, myvalue in self.iteritems():
Expand Down Expand Up @@ -3275,10 +3302,6 @@ def environ(self):
# Filtered by IUSE and implicit IUSE.
mydict["USE"] = self.get("PORTAGE_USE", "")

# Don't export AA to the ebuild environment in EAPIs that forbid it
if not eapi_exports_AA(eapi):
mydict.pop("AA", None)

if not eapi_exports_merge_type(eapi):
mydict.pop("MERGE_TYPE", None)

Expand Down