Merge branch 'fix/http_server_async_requests_on_same_socket_blocks_v5.4' into 'release/v5.4'

Fix async requests on same socket blocking server (v5.4)

See merge request espressif/esp-idf!41998
This commit is contained in:
Jiang Jiang Jian
2025-09-20 00:31:30 +08:00
3 changed files with 31 additions and 9 deletions

View File

@@ -41,6 +41,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
*/

View File

@@ -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) {

View File

@@ -12,6 +12,7 @@
#include <esp_http_server.h>
#include "esp_httpd_priv.h"
#include <netinet/tcp.h>
#include "ctrl_sock.h"
static const char *TAG = "httpd_txrx";
@@ -655,6 +656,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;
@@ -662,6 +668,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;
}