Conversation
This was referenced Sep 11, 2026
Author
|
@ychescale9 could you take a look at this when you have a chance? |
Fixes ReactiveCircus#432, duplicate of ReactiveCircus#489. sys.boot_completed only means system_server reached its final boot phase - it doesn't guarantee every service has registered with ServiceManager by the time that property is externally observable over adb. `input keyevent 82` right after boot can race InputManagerService's own registration and throw ServiceNotFoundException: No service published for: input. Adds waitForService(), polling `service check <name>` before the input keyevent call. Independently reproduced with the same stack trace in kiwix/kiwix-android#5047.
soloturn
force-pushed
the
fix/wait-for-input-service-and-settings-provider
branch
from
September 11, 2026 11:45
ebfd7d9 to
ab495a9
Compare
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite `steps:` can't loop over a `uses:` step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay exactly as before, handled by the existing separate "Create AVD and generate snapshot for caching" step upstream of this one - this only takes over AVD creation + emulator launch + boot/input-service wait + test script + teardown, since that's the part that needs retrying. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against.
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite `steps:` can't loop over a `uses:` step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay exactly as before, handled by the existing separate "Create AVD and generate snapshot for caching" step upstream of this one - this only takes over AVD creation + emulator launch + boot/input-service wait + test script + teardown, since that's the part that needs retrying. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against.
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 11, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Four more bugs found live, running this on a real matrix job: - sdkmanager_bin/avdmanager_bin resolved via `find "$ANDROID_HOME" -maxdepth 4 -name ...`, which silently returned empty on one runner, turning "binary not found" into a cryptic "yes: Broken pipe" instead of a clear error. Both now use the fixed cmdline-tools path actions/runner-images actually uses, with an explicit check. - `yes | sdkmanager --licenses` failed the whole step even when sdkmanager itself exited 0: composite shell: bash steps always run as `bash -e -o pipefail` regardless of this script's own `set` line, and once sdkmanager has nothing left to accept it closes stdin, giving `yes` a SIGPIPE that pipefail treats as a pipeline failure. Now `|| true`. - Starting the emulator before any adb server exists races adb's device-registration handshake - observed going permanently "offline" and never recovering, so a getprop poll loop waits out the full timeout for a device that will never answer. Fixed two ways: `adb start-server` before the loop so the server is already up when the emulator registers, and swapping the blind getprop poll for `adb wait-for-device` (bounded to 60s) first - that blocks on adb's own transport-state tracking instead of repeatedly racing the daemon autostart with one-shot `adb shell` calls. - `adb emu kill` alone can't guarantee the emulator actually dies: it needs a working adb connection, so on the offline-forever case above it silently no-ops (`2>/dev/null || true`) and leaves the process running - which then made every subsequent attempt in this same run fail instantly with "Running multiple emulators with the same AVD", while still burning the full boot-poll timeout before giving up. kill_emulator() now also kills the tracked PID directly and waits on it, regardless of adb connectivity. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 12, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Four more bugs found live, running this on a real matrix job: - sdkmanager_bin/avdmanager_bin resolved via `find "$ANDROID_HOME" -maxdepth 4 -name ...`, which silently returned empty on one runner, turning "binary not found" into a cryptic "yes: Broken pipe" instead of a clear error. Both now use the fixed cmdline-tools path actions/runner-images actually uses, with an explicit check. - `yes | sdkmanager --licenses` failed the whole step even when sdkmanager itself exited 0: composite shell: bash steps always run as `bash -e -o pipefail` regardless of this script's own `set` line, and once sdkmanager has nothing left to accept it closes stdin, giving `yes` a SIGPIPE that pipefail treats as a pipeline failure. Now `|| true`. - Starting the emulator before any adb server exists races adb's device-registration handshake - observed going permanently "offline" and never recovering, so a getprop poll loop waits out the full timeout for a device that will never answer. Fixed two ways: `adb start-server` before the loop so the server is already up when the emulator registers, and swapping the blind getprop poll for `adb wait-for-device` (bounded to 60s) first - that blocks on adb's own transport-state tracking instead of repeatedly racing the daemon autostart with one-shot `adb shell` calls. - `adb emu kill` alone can't guarantee the emulator actually dies: it needs a working adb connection, so on the offline-forever case above it silently no-ops (`2>/dev/null || true`) and leaves the process running - which then made every subsequent attempt in this same run fail instantly with "Running multiple emulators with the same AVD", while still burning the full boot-poll timeout before giving up. kill_emulator() now also kills the tracked PID directly and waits on it, regardless of adb connectivity. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 12, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Four more bugs found live, running this on a real matrix job: - sdkmanager_bin/avdmanager_bin resolved via `find "$ANDROID_HOME" -maxdepth 4 -name ...`, which silently returned empty on one runner, turning "binary not found" into a cryptic "yes: Broken pipe" instead of a clear error. Both now use the fixed cmdline-tools path actions/runner-images actually uses, with an explicit check. - `yes | sdkmanager --licenses` failed the whole step even when sdkmanager itself exited 0: composite shell: bash steps always run as `bash -e -o pipefail` regardless of this script's own `set` line, and once sdkmanager has nothing left to accept it closes stdin, giving `yes` a SIGPIPE that pipefail treats as a pipeline failure. Now `|| true`. - Starting the emulator before any adb server exists races adb's device-registration handshake - observed going permanently "offline" and never recovering, so a getprop poll loop waits out the full timeout for a device that will never answer. Fixed two ways: `adb start-server` before the loop so the server is already up when the emulator registers, and swapping the blind getprop poll for `adb wait-for-device` (bounded to 60s) first - that blocks on adb's own transport-state tracking instead of repeatedly racing the daemon autostart with one-shot `adb shell` calls. - `adb emu kill` alone can't guarantee the emulator actually dies: it needs a working adb connection, so on the offline-forever case above it silently no-ops (`2>/dev/null || true`) and leaves the process running - which then made every subsequent attempt in this same run fail instantly with "Running multiple emulators with the same AVD", while still burning the full boot-poll timeout before giving up. kill_emulator() now also kills the tracked PID directly and waits on it, regardless of adb connectivity. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
soloturn
added a commit
to soloturn/kiwix-android
that referenced
this pull request
Sep 12, 2026
GitHub Actions composite steps can't loop over a uses: step, which is why the previous version needed one hand-written YAML block per attempt - going from 3 attempts to 4 meant copy-pasting a whole new block, and it would again for 5, 6, etc. while waiting for ReactiveCircus/android-emulator-runner#495 to ship. Replaces that with a single script step wrapping a real bash loop. SDK installation and the initial AVD/snapshot stay handled by the existing separate 'Create AVD and generate snapshot for caching' step upstream of this one on a cache miss; on a cache hit that step (and the SDK install it triggers) is skipped entirely, so this step also has to: - default ANDROID_AVD_HOME itself (only exported by that step's SDK install) - install avdmanager/emulator/the system image itself before using them (same reason - reactivecircus/android-emulator-runner normally does this on every run regardless of AVD cache state; every other direct use of it elsewhere in this workflow still does) Both caught live watching this run on a real cache-hit path, not in review. Preserves the two behaviors the old 3(4)-attempt version had: attempt 1 reuses the cached AVD/snapshot (-no-snapshot-save, no forced recreation) exactly like before; only retries force a fresh AVD and a genuinely cold boot (-no-snapshot), so a retry isn't just re-hitting whatever state the first attempt already failed against. Four more bugs found live, running this on a real matrix job: - sdkmanager_bin/avdmanager_bin resolved via `find "$ANDROID_HOME" -maxdepth 4 -name ...`, which silently returned empty on one runner, turning "binary not found" into a cryptic "yes: Broken pipe" instead of a clear error. Both now use the fixed cmdline-tools path actions/runner-images actually uses, with an explicit check. - `yes | sdkmanager --licenses` failed the whole step even when sdkmanager itself exited 0: composite shell: bash steps always run as `bash -e -o pipefail` regardless of this script's own `set` line, and once sdkmanager has nothing left to accept it closes stdin, giving `yes` a SIGPIPE that pipefail treats as a pipeline failure. Now `|| true`. - Starting the emulator before any adb server exists races adb's device-registration handshake - observed going permanently "offline" and never recovering, so a getprop poll loop waits out the full timeout for a device that will never answer. Fixed two ways: `adb start-server` before the loop so the server is already up when the emulator registers, and swapping the blind getprop poll for `adb wait-for-device` (bounded to 60s) first - that blocks on adb's own transport-state tracking instead of repeatedly racing the daemon autostart with one-shot `adb shell` calls. - `adb emu kill` alone can't guarantee the emulator actually dies: it needs a working adb connection, so on the offline-forever case above it silently no-ops (`2>/dev/null || true`) and leaves the process running - which then made every subsequent attempt in this same run fail instantly with "Running multiple emulators with the same AVD", while still burning the full boot-poll timeout before giving up. kill_emulator() now also kills the tracked PID directly and waits on it, regardless of adb connectivity. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #432, duplicate of #489.
sys.boot_completedonly meanssystem_serverreached its final boot phase - it doesn't guarantee every service has registered withServiceManagerby the time that property is externally observable over adb.input keyevent 82right after boot can raceInputManagerService's own registration:Independently reproduced with this exact stack trace in kiwix/kiwix-android#5047.
Fix
waitForService(port, 'input')pollsadb shell service check inputbefore theinput keyevent 82call, instead of assuming it's ready oncewaitForDevice()returns.Test plan
npm run lintcleannpm run build(tsc) clean,lib/regeneratednpm test- all 32 existing tests pass