fix(ota): defer remote actions during updates - #145
Merged
Conversation
ODevStudio
force-pushed
the
audit/pr-017-defer-ota-remote-actions
branch
from
August 13, 2026 13:49
63bf149 to
3427df9
Compare
ODevStudio
force-pushed
the
audit/pr-017-defer-ota-remote-actions
branch
from
August 13, 2026 14:36
eff76b0 to
bff8810
Compare
ODevStudio
marked this pull request as ready for review
August 13, 2026 14:53
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.
Summary
Root Cause
processWsPendingCmds()could execute remote actions while OTA was active. Client reset and OTA completion initially shared one pending bit, an extracted batch could escape when ElegantOTA started concurrently, and callback-owned soft-sleep state could make a later wake lose to an earlier pending sleep.A flag recheck under
wsPendingMuxwas insufficient. ElegantOTA could start immediately after the recheck but before hardware dispatch. Restoring the old batch with|=also resurrected older display, low-power, sleep, or timer commands over newer pending replacements.Implementation
WSP_OTA_RESET,pendingOtaResetAt, andremoteQueueOtaResetAt(); ordinary resets retainWSP_RESET.processWsPendingCmds()andonOTAStart()shareotaDispatchMutex. The dispatcher holds it across the complete extracted batch, so OTA start either waits for in-flight hardware work or publishes active OTA before the dispatcher rechecks.Safety / Reliability Impact
Client resets cannot interrupt an active flash write. Display, rail, timer, sample, gyro, duplicate-update, and power actions remain queued during OTA. The lifecycle mutex is a normal task mutex, not a critical section, so interrupts remain enabled during hardware dispatch.
Compatibility
No BLE, USB, WebSocket, manifest, storage, or OTA packet format changes. Remote actions received during a cancelled or failed update remain queued and run afterward; successful OTA completion still reboots through the main loop. Native, grinder, custom, and hardware targets were intentionally not run locally.
Regression Coverage
tools/test_ota_reboot_routing_contract.pynow covers ordinary-reset deferral, combined extraction/OTA-start/newer-command restoration for every replacement group, lifecycle-lock placement, rapid sleep/wake replacement, and pull-OTA power-action preservation.tools/test_soft_sleep_ads_wake.pyverifies both remote transports use main-loop sleep transitions.Verification
python tools/test_ota_reboot_routing_contract.pypython tools/test_soft_sleep_ads_wake.pypython tools/test_pull_ota_contract.pypython tools/test_ota_input_isolation_contract.pypython tools/test_ota_rollback_contract.pypython tools/test_charging_wake_contract.pypython tools/test_ble_subscription_contract.pypython tools/test_ai_docs_contract.pypio run -e esp32s3with an isolatedPLATFORMIO_CORE_DIRgit diff --checkAll passed. The ESP32-S3 build retains only the existing volatile-increment warnings in
src/wifi_setup.cpp.Hardware Verification
Not run. No physical concurrent remote-command traffic, OTA upload, flash write, cancellation, failure, or reboot was exercised.
Related Work
PR #141 isolates USB and physical-button input during OTA. PRs #142 and #144 restore soft-sleep hardware for pull and asynchronous OTA entry. PR #143 defers remote wake state publication until main-loop recovery.