From 321233b4f0a3e45b13a11d46d276ef462f7ff677 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);