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.
This commit is contained in:
Jin Cheng
2026-05-26 13:44:47 +08:00
parent 4efde1556a
commit 0820e16617
2 changed files with 57 additions and 24 deletions
@@ -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);
}
}
@@ -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, &param);
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(&param.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, &param);
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(&param.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, &param);
}
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, &param);
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, &param);
}
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, &param);
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, &param);
}
break;
default:
BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __func__, msg->act);