diff --git a/components/esp_http_server/src/esp_httpd_priv.h b/components/esp_http_server/src/esp_httpd_priv.h index f161f424f4..54c6923c6d 100644 --- a/components/esp_http_server/src/esp_httpd_priv.h +++ b/components/esp_http_server/src/esp_httpd_priv.h @@ -37,6 +37,19 @@ extern "C" { /* Formats a log string to prepend context function name */ #define LOG_FMT(x) "%s: " x, __func__ +/** + * @brief Control message data structure for internal use. Sent to control socket. + */ +struct httpd_ctrl_data { + enum httpd_ctrl_msg { + HTTPD_CTRL_SHUTDOWN, + HTTPD_CTRL_WORK, + HTTPD_CTRL_MAX, + } hc_msg; + httpd_work_fn_t hc_work; + void *hc_work_arg; +}; + /** * @brief Thread related data for internal use */ diff --git a/components/esp_http_server/src/httpd_main.c b/components/esp_http_server/src/httpd_main.c index fd434e87ae..943075317f 100644 --- a/components/esp_http_server/src/httpd_main.c +++ b/components/esp_http_server/src/httpd_main.c @@ -133,15 +133,6 @@ exit: return ESP_FAIL; } -struct httpd_ctrl_data { - enum httpd_ctrl_msg { - HTTPD_CTRL_SHUTDOWN, - HTTPD_CTRL_WORK, - } hc_msg; - httpd_work_fn_t hc_work; - void *hc_work_arg; -}; - esp_err_t httpd_queue_work(httpd_handle_t handle, httpd_work_fn_t work, void *arg) { if (handle == NULL || work == NULL) { diff --git a/components/esp_http_server/src/httpd_txrx.c b/components/esp_http_server/src/httpd_txrx.c index 4ddd267e0e..4ab4891394 100644 --- a/components/esp_http_server/src/httpd_txrx.c +++ b/components/esp_http_server/src/httpd_txrx.c @@ -12,6 +12,7 @@ #include #include "esp_httpd_priv.h" #include +#include "ctrl_sock.h" static const char *TAG = "httpd_txrx"; @@ -691,6 +692,11 @@ esp_err_t httpd_req_async_handler_complete(httpd_req_t *r) return ESP_ERR_INVALID_ARG; } + // Get server handle and control socket info before freeing the request + struct httpd_data *hd = (struct httpd_data *) r->handle; + int msg_fd = hd->msg_fd; + int port = hd->config.ctrl_port; + struct httpd_req_aux *ra = r->aux; ra->sd->for_async_req = false; free(ra->scratch); @@ -701,6 +707,18 @@ esp_err_t httpd_req_async_handler_complete(httpd_req_t *r) free(r->aux); free(r); + // Send a dummy control message(httpd_ctrl_data) to unblock the main HTTP server task from the select() call. + // Since the current connection FD was marked as inactive for async requests, the main task + // will now re-add this FD to its select() descriptor list. This ensures that subsequent requests + // on the same FD are processed correctly + struct httpd_ctrl_data msg = {.hc_msg = HTTPD_CTRL_MAX}; + int ret = cs_send_to_ctrl_sock(msg_fd, port, &msg, sizeof(msg)); + if (ret < 0) { + ESP_LOGW(TAG, LOG_FMT("failed to send socket notification")); + return ESP_FAIL; + } + + ESP_LOGD(TAG, LOG_FMT("socket notification sent")); return ESP_OK; }