mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(esp_event): free queued legacy cleanup ctx on loop delete
When a loop is deleted while an internal legacy "cleanup" event is still queued (posted by a deferred self-unregistration from within a handler), esp_event_loop_delete() drained the queue but only freed the post payload, leaking the heap copy of the handler context allocated for the legacy path. Free ctx->handler_ctx for queued legacy cleanup events while draining the queue, mirroring the cleanup done in esp_event_loop_run(). Add a regression test that leaves a legacy cleanup event queued and asserts no memory is leaked on loop deletion.
This commit is contained in:
@@ -830,6 +830,12 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop)
|
||||
// Drop existing posts on the queue
|
||||
esp_event_post_instance_t post;
|
||||
while (xQueueReceive(loop->queue, &post, 0) == pdTRUE) {
|
||||
if (post.base == esp_event_handler_cleanup) {
|
||||
esp_event_remove_handler_context_t* ctx = (esp_event_remove_handler_context_t*)post.data.ptr;
|
||||
if (ctx->legacy) {
|
||||
free(ctx->handler_ctx);
|
||||
}
|
||||
}
|
||||
post_instance_delete(&post);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -183,6 +183,30 @@ TEST_CASE("registering event twice with same handler yields updated handler arg"
|
||||
TEST_ASSERT_EQUAL(1, count_second);
|
||||
}
|
||||
|
||||
static void self_unregister_legacy_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
||||
{
|
||||
esp_event_loop_handle_t loop = (esp_event_loop_handle_t) event_handler_arg;
|
||||
TEST_ESP_OK(esp_event_handler_unregister_with(loop, event_base, event_id, self_unregister_legacy_handler));
|
||||
}
|
||||
|
||||
/* A legacy handler unregistering itself defers removal via an internal cleanup event
|
||||
* left on the queue. Deleting the loop must drain it without leaking. */
|
||||
TEST_CASE("deleting loop with queued legacy cleanup event does not leak", "[event][linux]")
|
||||
{
|
||||
EV_LoopFix loop_fix;
|
||||
|
||||
TEST_ESP_OK(esp_event_handler_register_with(loop_fix.loop,
|
||||
s_test_base1,
|
||||
TEST_EVENT_BASE1_EV1,
|
||||
self_unregister_legacy_handler,
|
||||
loop_fix.loop));
|
||||
|
||||
TEST_ESP_OK(esp_event_post_to(loop_fix.loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY));
|
||||
|
||||
/* ZERO_DELAY runs a single event, leaving the deferred cleanup event queued. */
|
||||
TEST_ESP_OK(esp_event_loop_run(loop_fix.loop, ZERO_DELAY));
|
||||
}
|
||||
|
||||
TEST_CASE("registering event handler instance twice works", "[event][linux]")
|
||||
{
|
||||
EV_LoopFix loop_fix;
|
||||
|
||||
Reference in New Issue
Block a user