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}"

Reply via email to