From 5a8aedf53d431e2f97b66c9a504e33d2a5efddfc Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Tue, 25 Aug 2026 00:16:27 -0500 Subject: [PATCH] Read sdkmanager's status, not the status of the yes feeding it run-e2e.sh installs a missing system image with yes | sdkmanager --install "$pkg" > /dev/null 2>&1 || { echo " FAILED to install"; ... } `yes` never ends. The moment sdkmanager exits and closes the pipe, `yes` dies of SIGPIPE with 141, and this script runs under `pipefail`, which takes the rightmost non-zero status. So a package that installed perfectly reported "FAILED to install $pkg" and returned 1. R32 filed this PLAUSIBLE on shell semantics, unexecuted. It is demonstrated now: set -o pipefail; yes | true -> 141 (three runs, three times) set -o pipefail; yes | sh -c 'exit 3' -> 3 ${PIPESTATUS[1]} for those two -> 0 and 3 The pipeline status genuinely cannot tell a clean install from a broken one; PIPESTATUS can. That is the whole change -- no restructuring of the licence flow, so a fresh SDK still gets its licences accepted exactly as before. `echo no | avdmanager` eleven lines below is deliberately left alone, and the comment says so. One line fits the pipe buffer, so echo has already exited before the close and there is no signal to receive: `echo no | true` measured 0 on five consecutive runs against `yes | true`'s 141 on three. Only an unbounded producer is exposed. Someone reading this fix later would otherwise "fix" the echo too and change a line that was never wrong. Why it went unnoticed: it only misfires when the image is ABSENT, and every existing checkout already has the images. R32 noted the branch that made this the normal path. The failure is also silent in the worst way -- the install succeeds, the script says it failed, and the AVD is then created from a package that is really there. shellcheck clean at the pinned digest (0.11.0, the version CI runs), bash -n clean. Closes #41. --- null | 0 tools/local-emulator/run-e2e.sh | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 null diff --git a/null b/null new file mode 100644 index 0000000..e69de29 diff --git a/tools/local-emulator/run-e2e.sh b/tools/local-emulator/run-e2e.sh index 095f042..e09b8d5 100755 --- a/tools/local-emulator/run-e2e.sh +++ b/tools/local-emulator/run-e2e.sh @@ -236,10 +236,24 @@ ensure_avd() { else if [ ! -d "$img_dir" ]; then echo " installing $pkg" - yes | sdkmanager --install "$pkg" > /dev/null 2>&1 || { + # Read sdkmanager's own status, not the pipeline's. `yes` never ends, so the moment + # sdkmanager exits and closes the pipe, `yes` dies of SIGPIPE with 141 -- and this + # script runs under `pipefail`, which takes the rightmost NON-ZERO status. A package + # that installed perfectly therefore reported "FAILED to install". + # + # Measured rather than reasoned: under `set -o pipefail`, `yes | true` exits 141 on + # every run, and `yes | sh -c 'exit 3'` exits 3 -- so the pipeline status cannot tell + # a clean install from a broken one, while ${PIPESTATUS[1]} reports 0 and 3. + # + # The `echo no | avdmanager` below is deliberately NOT changed. One line fits the pipe + # buffer, so echo has already exited before the close and there is no signal to + # receive; `echo no | true` measured 0 on every run. Only an unbounded producer is + # exposed to this. + yes | sdkmanager --install "$pkg" > /dev/null 2>&1 + if [ "${PIPESTATUS[1]}" -ne 0 ]; then echo " FAILED to install $pkg" return 1 - } + fi fi echo " creating AVD $avd from $pkg" echo no | avdmanager create avd -n "$avd" -k "$pkg" -d pixel_6 --force > /dev/null 2>&1 || {