Synchronize ESP32 BLE serial frame queues#2063
Open
robekl wants to merge 1 commit intomeshcore-dev:devfrom
Open
Synchronize ESP32 BLE serial frame queues#2063robekl wants to merge 1 commit intomeshcore-dev:devfrom
robekl wants to merge 1 commit intomeshcore-dev:devfrom
Conversation
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
checkRecvFrame()while callbacks can append to themIssue
SerialBLEInterfacecurrently sharesrecv_queue,send_queue, and their length counters between BLE callback context and the main loop.The problematic pattern is:
onWrite()appends a received BLE frame directly intorecv_queueand incrementsrecv_queue_lenwriteFrame()appends outbound frames directly intosend_queueand incrementssend_queue_lencheckRecvFrame()consumes the first element of each queue and compacts the remaining array entries in placeThat means the BLE callback can be writing queue entries and lengths at the same time that the main loop is reading and shifting those same arrays. On ESP32, those BLE callbacks are not guaranteed to run in the same execution context as the app loop, so the current code has a real producer/consumer race:
Fix
This change keeps the existing queue sizes and behavior, but changes the queue implementation so callback and loop code stop mutating the same array layout concurrently.
Specifically:
portENTER_CRITICAL/portEXIT_CRITICALsectiononWrite()only enqueues a complete received framewriteFrame()only enqueues a complete outbound framecheckRecvFrame()dequeues stable frames and no longer shifts queue contents in placeWhy this fixes it
The old race existed because the producer and consumer both rewrote the queue storage layout. Once
checkRecvFrame()removed the first element, it had to copy every remaining entry down by one slot, which directly overlapped with callback-time appends.With the ring-buffer handoff:
That removes the window where callback and loop code can corrupt each other's queue state or frame contents.
Validation
pio run -e Heltec_v3_companion_radio_ble