Skip to content

Commit 67bd7e3

Browse files
committed
fix(websocket): Fix reconnection data loss and memory leaks
1. Reset frame parsing state (payload_len, payload_offset, last_opcode) on new connection 2. Free errormsg_buffer in esp_websocket_client_disconnect() 3. Destroy transport_list immediately in esp_websocket_client_stop
1 parent d5a2836 commit 67bd7e3

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

components/esp_websocket_client/esp_websocket_client.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ static esp_err_t esp_websocket_client_abort_connection(esp_websocket_client_hand
245245
{
246246
ESP_WS_CLIENT_STATE_CHECK(TAG, client, return ESP_FAIL);
247247

248+
// Note: This function must be called with client->lock already held
249+
// The caller is responsible for acquiring the lock before calling
250+
248251
// CRITICAL: Check if already closing/closed to prevent double-close
249252
if (client->state == WEBSOCKET_STATE_CLOSING || client->state == WEBSOCKET_STATE_UNKNOW) {
250253
ESP_LOGW(TAG, "Connection already closing/closed, skipping abort");
@@ -267,6 +270,16 @@ static esp_err_t esp_websocket_client_abort_connection(esp_websocket_client_hand
267270
client->error_handle.error_type = error_type;
268271
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_DISCONNECTED, NULL, 0);
269272

273+
if (client->errormsg_buffer) {
274+
ESP_LOGI(TAG, "Freeing error buffer (%d bytes) - Free heap: %" PRIu32 " bytes",
275+
client->errormsg_size, esp_get_free_heap_size());
276+
free(client->errormsg_buffer);
277+
client->errormsg_buffer = NULL;
278+
client->errormsg_size = 0;
279+
} else {
280+
ESP_LOGI(TAG, "Disconnect - Free heap: %" PRIu32 " bytes", esp_get_free_heap_size());
281+
}
282+
270283
return ESP_OK;
271284
}
272285

@@ -1183,6 +1196,11 @@ static void esp_websocket_client_task(void *pv)
11831196
client->state = WEBSOCKET_STATE_CONNECTED;
11841197
client->wait_for_pong_resp = false;
11851198
client->error_handle.error_type = WEBSOCKET_ERROR_TYPE_NONE;
1199+
client->payload_len = 0;
1200+
client->payload_offset = 0;
1201+
client->last_fin = false;
1202+
client->last_opcode = WS_TRANSPORT_OPCODES_NONE;
1203+
11861204
esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_CONNECTED, NULL, 0);
11871205
break;
11881206
case WEBSOCKET_STATE_CONNECTED:
@@ -1273,6 +1291,7 @@ static void esp_websocket_client_task(void *pv)
12731291
xSemaphoreTakeRecursive(client->lock, lock_timeout);
12741292
if (esp_websocket_client_recv(client) == ESP_FAIL) {
12751293
ESP_LOGE(TAG, "Error receive data");
1294+
// Note: Already holding client->lock from line above
12761295
esp_websocket_client_abort_connection(client, WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT);
12771296
}
12781297
xSemaphoreGiveRecursive(client->lock);
@@ -1357,7 +1376,16 @@ esp_err_t esp_websocket_client_stop(esp_websocket_client_handle_t client)
13571376
return ESP_FAIL;
13581377
}
13591378

1360-
return stop_wait_task(client);
1379+
esp_err_t ret = stop_wait_task(client);
1380+
1381+
if (client->transport_list) {
1382+
ESP_LOGI(TAG, "Destroying transport list to free resources immediately");
1383+
esp_transport_list_destroy(client->transport_list);
1384+
client->transport_list = NULL;
1385+
client->transport = NULL;
1386+
}
1387+
1388+
return ret;
13611389
}
13621390

13631391
static int esp_websocket_client_send_close(esp_websocket_client_handle_t client, int code, const char *additional_data, int total_len, TickType_t timeout)

0 commit comments

Comments
 (0)