Skip to content

fix: reset boot_fail_count before OTA restart to prevent false recovery#10983

Open
huhuanming wants to merge 12 commits intorelease/v6.1.0from
fix/reset-boot-fail-count-before-ota-restart
Open

fix: reset boot_fail_count before OTA restart to prevent false recovery#10983
huhuanming wants to merge 12 commits intorelease/v6.1.0from
fix/reset-boot-fail-count-before-ota-restart

Conversation

@huhuanming
Copy link
Copy Markdown
Contributor

@huhuanming huhuanming commented Mar 31, 2026

Summary

  • After installBundle completes, RNRestart.restart() force-kills the process without triggering Activity.onStop(), so boot_fail_count is never reset
  • If the previous boot was short-lived (e.g. OTA install completed during early initialization), the counter stays elevated and subsequent restarts quickly accumulate to the threshold of 3, falsely triggering recovery mode
  • Call BootRecovery.markBootSuccess() (wrapped in try/catch) before every planned RNRestart in installBundle, restart, and switchBundle to reset the counter, since these are intentional restarts — not crash-loops

Root Cause

Timeline reproduced from actual Android logs:

  1. Boot 3 (17:53:56): boot_fail_count 0→1, loads bundle 7366896
  2. 17:53:59 (only 3s later): installBundle completes, schedules RNRestart.restart()
  3. ~17:54:01: Process force-killed, onStop() never called, count stays at 1
  4. New bundle 7701116 fails on first load (count 1→2), restarts again (count 2→3)
  5. Recovery mode triggered — but bundle 7701116 itself is fine (boots normally after user taps "Not Now")

Test plan

  • Install an OTA bundle update on Android, verify restart does not falsely trigger recovery page
  • Install an OTA bundle update on iOS, verify restart does not falsely trigger recovery page
  • Use switchBundle to switch to another bundle version, confirm recovery mode is not triggered
  • Simulate real consecutive crashes (3x), confirm recovery mode still triggers correctly

When installBundle completes and schedules RNRestart.restart(), the
process is force-killed without triggering Activity.onStop(), so the
boot_fail_count is never reset. If the previous boot was short-lived
(e.g. OTA install completed during early initialization), the counter
stays elevated and subsequent restarts quickly accumulate to the
threshold of 3, falsely triggering recovery mode.

Call BootRecovery.markBootSuccess() before every planned RNRestart in
installBundle, restart, and switchBundle to reset the counter, since
these are intentional restarts and not crash-loops.
@revan-zhang
Copy link
Copy Markdown
Contributor

revan-zhang commented Mar 31, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

devin-ai-integration[bot]

This comment was marked as resolved.

@huhuanming huhuanming enabled auto-merge (squash) March 31, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants