From 5d0b77797b7a35a1cc551f15b383d78f5383f4fb 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 b0b2ee13a3c..ccfb5b0c7cf 100644 --- a/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c +++ b/components/bt/host/bluedroid/bta/sdp/bta_sdp_act.c @@ -524,6 +524,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"); @@ -638,8 +644,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 964d375327a..871fe9fc5fa 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 @@ -64,6 +64,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; } @@ -1221,7 +1233,7 @@ static void btc_sdp_deinit(void) BTA_SdpRemoveRecordByUser((void*)i); } } - BTA_SdpDisable(); + ret = BTA_SdpDisable(); } while(0); if (ret != ESP_SDP_SUCCESS) { @@ -1407,34 +1419,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);