fix(console): Memory leaks after deinit

This commit is contained in:
Guillaume Souchere
2025-02-06 13:21:03 +01:00
parent 5b2f2e05f3
commit 203b3b5a4e
8 changed files with 62 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -376,7 +376,18 @@ esp_err_t esp_console_register_help_command(void)
.argtable = &help_args
};
return esp_console_cmd_register(&command);
return ESP_OK;
}
esp_err_t esp_console_deregister_help_command(void)
{
free(help_args.help_cmd);
free(help_args.verbose_level);
free(help_args.end);
return esp_console_cmd_deregister("help");
}
esp_err_t esp_console_set_help_verbose_level(esp_console_help_verbose_level_e verbose_level)
{
/* legal verbose level sanity check */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -331,6 +331,15 @@ const char *esp_console_get_hint(const char *buf, int *color, int *bold);
*/
esp_err_t esp_console_register_help_command(void);
/**
* @brief Deregister a 'help' command
*
* @return esp_err_t
* - ESP_OK on success
* - other on failure
*/
esp_err_t esp_console_deregister_help_command(void);
/**
* @brief Set the verbose level for 'help' command
*

View File

@@ -129,6 +129,22 @@ _exit:
return ret;
}
void esp_console_common_deinit(esp_console_repl_com_t *repl_com)
{
/* Unregister the heap function to avoid memory leak, since it is created
* every time a console init is called. */
esp_err_t ret = esp_console_deregister_help_command();
assert(ret == ESP_OK);
/* unregister eventfd to avoid memory leaks, since it is created every time a
* console init is called */
(void)esp_vfs_eventfd_unregister();
/* free the history to avoid memory leak, since it is created
* every time a console init is called. */
linenoiseHistoryFree();
}
esp_err_t esp_console_start_repl(esp_console_repl_t *repl)
{
esp_err_t ret = ESP_OK;

View File

@@ -315,6 +315,8 @@ static esp_err_t esp_console_repl_uart_delete(esp_console_repl_t *repl)
vSemaphoreDelete(repl_com->state_mux);
repl_com->state_mux = NULL;
esp_console_common_deinit(&uart_repl->repl_com);
esp_console_deinit();
uart_vfs_dev_use_nonblocking(uart_repl->uart_channel);
uart_driver_delete(uart_repl->uart_channel);
@@ -356,6 +358,8 @@ static esp_err_t esp_console_repl_usb_cdc_delete(esp_console_repl_t *repl)
vSemaphoreDelete(repl_com->state_mux);
repl_com->state_mux = NULL;
esp_console_common_deinit(&cdc_repl->repl_com);
esp_console_deinit();
free(cdc_repl);
_exit:
@@ -395,6 +399,8 @@ static esp_err_t esp_console_repl_usb_serial_jtag_delete(esp_console_repl_t *rep
vSemaphoreDelete(repl_com->state_mux);
repl_com->state_mux = NULL;
esp_console_common_deinit(&usb_serial_jtag_repl->repl_com);
esp_console_deinit();
usb_serial_jtag_vfs_use_nonblocking();
usb_serial_jtag_driver_uninstall();

View File

@@ -1265,6 +1265,7 @@ void linenoiseHistoryFree(void) {
free(history);
}
history = NULL;
history_len = 0;
}
/* This is the API call to add a new entry in the linenoise history.

View File

@@ -47,6 +47,7 @@ typedef struct {
void esp_console_repl_task(void *args);
esp_err_t esp_console_common_init(size_t max_cmdline_length, esp_console_repl_com_t *repl_com);
void esp_console_common_deinit(esp_console_repl_com_t *repl_com);
esp_err_t esp_console_setup_prompt(const char *prompt, esp_console_repl_com_t *repl_com);
esp_err_t esp_console_setup_history(const char *history_path,
uint32_t max_history_len,

View File

@@ -10,7 +10,12 @@
#include <sys/time.h>
// Some resources are lazy allocated (newlib locks) in the console code, the threshold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (150)
#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT (150)
static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
void set_leak_threshold(int threshold)
{
leak_threshold = threshold;
}
void setUp(void)
{
@@ -19,7 +24,8 @@ void setUp(void)
void tearDown(void)
{
unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_evaluate_leaks_direct(leak_threshold);
leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
}
void app_main(void)

View File

@@ -154,8 +154,11 @@ TEST_CASE("esp console repl test", "[console][ignore]")
vTaskDelay(pdMS_TO_TICKS(2000));
}
extern void set_leak_threshold(int threshold);
TEST_CASE("esp console repl deinit", "[console][ignore]")
{
set_leak_threshold(400);
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
TEST_ESP_OK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl));
@@ -165,14 +168,17 @@ TEST_CASE("esp console repl deinit", "[console][ignore]")
/* wait to make sure the task reaches linenoiseEdit function
* and gets stuck in the select */
vTaskDelay(pdMS_TO_TICKS(500));
vTaskDelay(pdMS_TO_TICKS(10));
/* call the delete function, this returns only when the repl task terminated */
const esp_err_t res = s_repl->del(s_repl);
/* wait to make sure the task reaches linenoiseEdit function
* and gets stuck in the select */
vTaskDelay(pdMS_TO_TICKS(10));
/* if this point is reached, the repl environment has been deleted successfully */
TEST_ASSERT(res == ESP_OK);
printf("-------------- %p\n", s_repl);
}
static const esp_console_cmd_t cmd_a = {