From 4d866dc5e1b88146285bd459a84ed61ce304665a Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Wed, 20 May 2026 19:14:00 +0800 Subject: [PATCH] fix(bt/bluedroid): fixed SDP deinit race with pending callbacks Cancel any active SDP search during disabling and mark the BTA SDP callbacks inactive so late search completions are not propagated after deinit. Guard BTC side SDP completion handling after cleanup to avoid null references. --- .../bt/host/bluedroid/bta/sdp/bta_sdp_act.c | 19 +++++- .../bluedroid/btc/profile/std/sdp/btc_sdp.c | 62 ++++++++++++------- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c index 9b4219c1679..acb32441841 100644 --- a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c +++ b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c @@ -480,6 +480,12 @@ void bta_sdp_search(tBTA_SDP_MSG *p_data) APPL_TRACE_DEBUG("SDP control block handle is null\n"); return; } + + if (bta_sdp_cb.p_dm_cback == NULL) { + APPL_TRACE_DEBUG("SDP is not active\n"); + return; + } + tBT_UUID *bta_sdp_search_uuid = osi_malloc(sizeof(tBT_UUID)); if (bta_sdp_search_uuid == NULL) { APPL_TRACE_DEBUG("SDP search param malloc failed\n"); @@ -594,8 +600,17 @@ void bta_sdp_disable(tBTA_SDP_MSG *p_data) APPL_TRACE_DEBUG("%s()\n", __func__); tBTA_SDP bta_sdp; bta_sdp.status = BTA_SDP_SUCCESS; - if (bta_sdp_cb.p_dm_cback) { - bta_sdp_cb.p_dm_cback(BTA_SDP_DISABLE_EVT, &bta_sdp, NULL); + tBTA_SDP_DM_CBACK *dm_cbk = bta_sdp_cb.p_dm_cback; + + bta_sdp_cb.p_dm_cback = NULL; + if (p_bta_sdp_cfg->p_sdp_db && (bta_sdp_cb.sdp_active != BTA_SDP_ACTIVE_NONE)) { + if (!SDP_CancelServiceSearch(p_bta_sdp_cfg->p_sdp_db)) { + bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE; + } + } + + if (dm_cbk) { + dm_cbk(BTA_SDP_DISABLE_EVT, &bta_sdp, NULL); } } diff --git a/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c b/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c index f9c0ee1c89c..d738c898f40 100644 --- a/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c +++ b/components/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c @@ -57,6 +57,18 @@ static void btc_sdp_cleanup(void) if (sdp_local_param_ptr) { #endif if (sdp_local_param.sdp_slot_mutex) { + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + for (int i = 0; i < SDP_MAX_RECORDS; i++) { + sdp_slot_t *slot = sdp_local_param.sdp_slots[i]; + if (slot) { + if (slot->record_data) { + osi_free(slot->record_data); + } + osi_free(slot); + sdp_local_param.sdp_slots[i] = NULL; + } + } + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); osi_mutex_free(&sdp_local_param.sdp_slot_mutex); sdp_local_param.sdp_slot_mutex = NULL; } @@ -1129,7 +1141,7 @@ static void btc_sdp_deinit(void) BTA_SdpRemoveRecordByUser((void*)i); } } - BTA_SdpDisable(); + ret = BTA_SdpDisable(); } while(0); if (ret != ESP_SDP_SUCCESS) { @@ -1315,34 +1327,40 @@ void btc_sdp_cb_handler(btc_msg_t *msg) btc_sdp_cb_to_app(ESP_SDP_DEINIT_EVT, ¶m); break; case BTA_SDP_SEARCH_COMP_EVT: - // SDP search completed, now can be searched again - sdp_local_param.search_allowed = true; + if (is_sdp_init()) { + // SDP search completed, now can be searched again + sdp_local_param.search_allowed = true; - param.search.status = p_data->sdp_search_comp.status; - memcpy(param.search.remote_addr, p_data->sdp_search_comp.remote_addr, sizeof(BD_ADDR)); - bta_to_btc_uuid(¶m.search.sdp_uuid, &p_data->sdp_search_comp.uuid); - param.search.record_count = p_data->sdp_search_comp.record_count; - param.search.records = (esp_bluetooth_sdp_record_t *)p_data->sdp_search_comp.records; - btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m); + param.search.status = p_data->sdp_search_comp.status; + memcpy(param.search.remote_addr, p_data->sdp_search_comp.remote_addr, sizeof(BD_ADDR)); + bta_to_btc_uuid(¶m.search.sdp_uuid, &p_data->sdp_search_comp.uuid); + param.search.record_count = p_data->sdp_search_comp.record_count; + param.search.records = (esp_bluetooth_sdp_record_t *)p_data->sdp_search_comp.records; + btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m); + } break; case BTA_SDP_CREATE_RECORD_USER_EVT: - param.create_record.status = p_data->sdp_create_record.status; - param.create_record.record_handle = p_data->sdp_create_record.handle; - btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m); + if (is_sdp_init()) { + param.create_record.status = p_data->sdp_create_record.status; + param.create_record.record_handle = p_data->sdp_create_record.handle; + btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m); + } break; case BTA_SDP_REMOVE_RECORD_USER_EVT: - if (p_data->sdp_remove_record.status == BTA_SDP_SUCCESS) { - int slot_id = get_sdp_slot_id_by_handle(p_data->sdp_remove_record.handle); - if (slot_id < 0) { - p_data->sdp_remove_record.status = ESP_SDP_NO_CREATE_RECORD; - } else { - free_sdp_slot(slot_id); + if (is_sdp_init()) { + if (p_data->sdp_remove_record.status == BTA_SDP_SUCCESS) { + int slot_id = get_sdp_slot_id_by_handle(p_data->sdp_remove_record.handle); + if (slot_id < 0) { + p_data->sdp_remove_record.status = ESP_SDP_NO_CREATE_RECORD; + } else { + free_sdp_slot(slot_id); + } } - } - param.remove_record.status = p_data->sdp_remove_record.status; - param.remove_record.record_handle = p_data->sdp_remove_record.handle; - btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m); + param.remove_record.status = p_data->sdp_remove_record.status; + param.remove_record.record_handle = p_data->sdp_remove_record.handle; + btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m); + } break; default: BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __func__, msg->act);