commit: 3ad2af53976a71bd1d0c56f226f68479548f3a5e Author: Kerin Millar <kfm <AT> plushkava <DOT> net> AuthorDate: Wed Jun 4 17:01:14 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Wed Jun 4 19:57:05 2025 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=3ad2af53
estrip: obviate a race condition causing duplicate warnings The estrip utility forks itself so as to achieve a degree of parallelism. Unfortunately, it is also predisposed to raising warnings deep into the function call stack. Although a given worker process makes a point of never issuing the same type of warning more than once, it remains unaware of the activities of another. This gives rise to a race condition in which ewarn() may be invoked in parallel, causing redundant warnings whose lines are unpredictably interleaved. * FEATURES=installsources is enabled but the debugedit binary could not be * FEATURES=installsources is enabled but the debugedit binary could not be * found. This feature will not work unless debugedit is installed! * found. This feature will not work unless debugedit is installed! Work around this issue by writing out the warnings to files whose names differ only by incorporating the checksum of the warning. In order to obviate the race condition, a temporary file is written to, after which mv(1) is used to atomically replace the existing file, if any. These warnings are later collected and conveyed through the invocation of the ewarn() function, just before estrip exits. By no means do I consider this to be an ideal solution but it is, at least, both a coherent and effective one; not to mention that it can potentially be improved upon later. Bug: https://bugs.gentoo.org/832138 Signed-off-by: Kerin Millar <kfm <AT> plushkava.net> Signed-off-by: Sam James <sam <AT> gentoo.org> bin/estrip | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/bin/estrip b/bin/estrip index f1b7140c02..a659a90666 100755 --- a/bin/estrip +++ b/bin/estrip @@ -213,6 +213,30 @@ tmpdir="${T}/prepstrip" rm -rf "${tmpdir}" mkdir -p "${tmpdir}"/{inodes,splitdebug,sources} +# Atomically writes the standard input to a file whose name is formatted as +# "estrip-%u.warning", <checksum of input>. The existing contents of the file, +# if any, shall not be preserved. +stash_warning() { + local tempfile crc + + tempfile=$(mktemp -p "${T:?}" -- estrip.XXXXXXXXXX) \ + && crc=$(set -o pipefail; tee -- "${tempfile}" | cksum) \ + && mv -- "${tempfile}" "${T}/estrip-${crc% *}.warning" +} + +# Iterates over any files previously created by the stash_warning() function, +# conveying their respective lines through the invocation of ewarn. +raise_warnings() { + local logfile + + for logfile in "${T:?}"/estrip-*.warning; do + test -f "${logfile}" || continue + while read -r; do + ewarn "${REPLY}" + done < "${logfile}" + done +} + # Usage: save_elf_sources <elf> save_elf_sources() { # shellcheck disable=2317 @@ -220,8 +244,10 @@ save_elf_sources() { save_elf_sources() { :; } return elif ! hash "${name_of[debugedit]}" 2>/dev/null; then - ewarn "FEATURES=installsources is enabled but the debugedit binary could not be" - ewarn "found. This feature will not work unless debugedit is installed!" + stash_warning <<-'EOF' + FEATURES=installsources is enabled but the debugedit binary could not be + found. This feature will not work unless debugedit is installed! + EOF save_elf_sources() { :; } return fi @@ -262,8 +288,11 @@ dedup_elf_debug() { dedup_elf_debug() { :; } return elif ! hash "${name_of[dwz]}" 2>/dev/null; then - ewarn "FEATURES=dedupdebug is enabled but the dwz binary could not be" - ewarn "found. This feature will not work unless dwz is installed!" + # Write out a warning to a function-scoped log file, atomically. + stash_warning <<-'EOF' + FEATURES=dedupdebug is enabled but the dwz binary could not be + found. This feature will not work unless dwz is installed! + EOF dedup_elf_debug() { :; } return fi @@ -349,8 +378,10 @@ save_elf_debug() { "${x}") elif ! contains_word buildid "${warned_for[debugedit]}"; then warned_for[debugedit]+=" buildid" - ewarn "FEATURES=splitdebug is enabled but the debugedit binary could not be found" - ewarn "This feature will not work correctly with build IDs unless debugedit is installed!" + stash_warning <<-'EOF' + FEATURES=splitdebug is enabled but the debugedit binary could not be found + This feature will not work correctly with build IDs unless debugedit is installed! + EOF fi fi @@ -637,4 +668,7 @@ then done < <(find "${D%/}/${prepstrip_sources_dir#/}/" -type d -empty -print0) fi +# Collect any outstanding warnings and convey them through ewarn. +raise_warnings + rm -rf "${tmpdir}"
