Merge branch 'fix/console_stop_repl_join' into 'master'

fix(console): join the REPL task before esp_console_stop_repl frees it

See merge request espressif/esp-idf!52590
This commit is contained in:
Marius Vikhammer
2026-09-11 11:11:34 +08:00
4 changed files with 16 additions and 7 deletions

View File

@@ -455,6 +455,7 @@ esp_err_t esp_console_start_repl(esp_console_repl_t *repl);
* @brief Stop REPL environment
*
* @param[in] repl REPL handle returned from esp_console_new_repl_xxx
* @note This function waits for the console task to exit before it returns.
* @return
* - ESP_OK on success
* - others on failure

View File

@@ -29,10 +29,6 @@ void esp_console_repl_task(void *args)
* function is called. */
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
if (repl_com->state_mux != NULL) {
xSemaphoreTake(repl_com->state_mux, portMAX_DELAY);
}
/* Change standard input and output of the task if the requested UART is
* NOT the default one. This block will replace stdin, stdout and stderr.
*/
@@ -338,6 +334,10 @@ esp_err_t esp_console_new_repl_stdio(const esp_console_repl_config_t *repl_confi
_exit:
if (universal_repl) {
esp_console_deinit();
/* Only common_deinit() deletes state_mux, and the weak set_event_fd() never creates it. */
if (universal_repl->repl_com.state_mux) {
vSemaphoreDelete(universal_repl->repl_com.state_mux);
}
free(universal_repl);
}
if (ret_repl) {

View File

@@ -152,6 +152,10 @@ static esp_err_t esp_console_new_repl_uart_legacy(const esp_console_dev_uart_con
_exit:
if (uart_repl) {
esp_console_deinit();
/* Only common_deinit() deletes state_mux, and the weak set_event_fd() never creates it. */
if (uart_repl->repl_com.state_mux) {
vSemaphoreDelete(uart_repl->repl_com.state_mux);
}
free(uart_repl);
}
if (ret_repl) {

View File

@@ -85,12 +85,13 @@ esp_err_t esp_console_internal_set_event_fd(esp_console_repl_com_t *repl_com)
return ESP_FAIL;
}
repl_com->state_mux = xSemaphoreCreateMutex();
/* Empty on purpose, and the task only ever gives it, never takes it: a
* mutex created given lets a stop take it before the task has run. */
repl_com->state_mux = xSemaphoreCreateBinary();
if (repl_com->state_mux == NULL) {
ESP_LOGE(TAG, "state_mux create error");
return ESP_ERR_NO_MEM;
}
xSemaphoreGive(repl_com->state_mux);
return ESP_OK;
}
@@ -103,6 +104,7 @@ esp_err_t esp_console_common_deinit(esp_console_repl_com_t *repl_com)
{
// set the state to deinit to force the while loop in
// esp_console_repl_task to break
const bool was_started = (repl_com->state == CONSOLE_REPL_STATE_START);
repl_com->state = CONSOLE_REPL_STATE_DEINIT;
if (s_interrupt_reading_fd == -1) {
@@ -117,7 +119,9 @@ esp_err_t esp_console_common_deinit(esp_console_repl_com_t *repl_com)
// wait for the task to notify that
// esp_console_repl_task returned
assert(repl_com->state_mux != NULL);
xSemaphoreTake(repl_com->state_mux, portMAX_DELAY);
if (was_started) {
xSemaphoreTake(repl_com->state_mux, portMAX_DELAY);
}
// delete the semaphore for the repl state
vSemaphoreDelete(repl_com->state_mux);