From d586a6c8d4232d55968fde5771fcae597008e71f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 9 Aug 2026 14:54:01 -0500 Subject: [PATCH] Address review: check the reclaim close, log the mid-stream park - The late-OPEN_EVT reclaim was the one unchecked IDF call in the backend; a failed close there leaks a live link nothing tracks - The mid-stream services_released_ park now leaves a trace like its API-lost sibling, so a stuck GetServices is explicable from logs --- .../bluetooth_connection_bluedroid.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.cpp b/esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.cpp index d4bee3fe3e..625549ccb9 100644 --- a/esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.cpp +++ b/esphome/components/bluetooth_connection/bluetooth_connection_bluedroid.cpp @@ -380,7 +380,9 @@ static_assert(requires(BluedroidGattClient c, BluetoothConnection &conn) { c.str void BluedroidGattClient::stream_service_batch(BluetoothConnection &conn) { if (this->services_released_) { // Released under the stream: park without services-done so a partial - // list is never cached as authoritative. + // list is never cached as authoritative (the client retries after its + // GetServices timeout). + ESP_LOGW(TAG, "[%d] [%s] Services released mid-stream, parking", conn.connection_index_, conn.address_str_); conn.send_service_ = DONE_SENDING_SERVICES; return; } @@ -524,7 +526,8 @@ void BluedroidGattClient::handle_open_evt_(esp_ble_gattc_cb_param_t *param) { // teardown net gave up): close a won link, never resurrect the slot. ESP_LOGD(TAG, "[%d] OPEN_EVT in IDLE state (status=%d)", this->connection_index_, param->open.status); if (param->open.status == ESP_GATT_OK || param->open.status == ESP_GATT_ALREADY_OPEN) { - esp_ble_gattc_close(this->gattc_if_, param->open.conn_id); + // A failed close here leaks a live link nothing tracks; make it heard. + this->check_and_log_error_("esp_ble_gattc_close", esp_ble_gattc_close(this->gattc_if_, param->open.conn_id)); } return; }