From f90c9320d951533f0b661f5f7a48697bfd369191 Mon Sep 17 00:00:00 2001 From: Yukai Li Date: Mon, 23 May 2022 15:43:39 -0600 Subject: [PATCH] bt: Fix race condition when disconnect during TX (#1260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bt: Fix race condition when disconnect during TX * bt: Move flag clear to not be in middle of other logic * bt: Bail out of send bytes a little bit earlier Co-authored-by: gornekich Co-authored-by: あく --- applications/bt/bt_service/bt.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) mode change 100755 => 100644 applications/bt/bt_service/bt.c diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c old mode 100755 new mode 100644 index 4a7b6f659..4ea5d7358 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -167,7 +167,11 @@ static void bt_rpc_send_bytes_callback(void* context, uint8_t* bytes, size_t byt furi_assert(context); Bt* bt = context; - osEventFlagsClear(bt->rpc_event, BT_RPC_EVENT_ALL); + if(osEventFlagsGet(bt->rpc_event) & BT_RPC_EVENT_DISCONNECTED) { + // Early stop from sending if we're already disconnected + return; + } + osEventFlagsClear(bt->rpc_event, BT_RPC_EVENT_ALL & (~BT_RPC_EVENT_DISCONNECTED)); size_t bytes_sent = 0; while(bytes_sent < bytes_len) { size_t bytes_remain = bytes_len - bytes_sent; @@ -178,10 +182,14 @@ static void bt_rpc_send_bytes_callback(void* context, uint8_t* bytes, size_t byt furi_hal_bt_serial_tx(&bytes[bytes_sent], bytes_remain); bytes_sent += bytes_remain; } - uint32_t event_flag = - osEventFlagsWait(bt->rpc_event, BT_RPC_EVENT_ALL, osFlagsWaitAny, osWaitForever); + // We want BT_RPC_EVENT_DISCONNECTED to stick, so don't clear + uint32_t event_flag = osEventFlagsWait( + bt->rpc_event, BT_RPC_EVENT_ALL, osFlagsWaitAny | osFlagsNoClear, osWaitForever); if(event_flag & BT_RPC_EVENT_DISCONNECTED) { break; + } else { + // If we didn't get BT_RPC_EVENT_DISCONNECTED, then clear everything else + osEventFlagsClear(bt->rpc_event, BT_RPC_EVENT_ALL & (~BT_RPC_EVENT_DISCONNECTED)); } } } @@ -197,6 +205,8 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) { bt->status = BtStatusConnected; BtMessage message = {.type = BtMessageTypeUpdateStatus}; furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); + // Clear BT_RPC_EVENT_DISCONNECTED because it might be set from previous session + osEventFlagsClear(bt->rpc_event, BT_RPC_EVENT_DISCONNECTED); if(bt->profile == BtProfileSerial) { // Open RPC session bt->rpc_session = rpc_session_open(bt->rpc);