Skip to content

Commit cfc0560

Browse files
committed
fix(esp_http_server): Fix async requests on same socket blocking issue
1. In async requests, if the two or more requests are made on same socket then it used to block the second request. 2. The main thread is used to block on select call. And there done no FD_SET for particular fd. Closes #16998
1 parent ab2829d commit cfc0560

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

components/esp_http_server/src/esp_httpd_priv.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ extern "C" {
3737
/* Formats a log string to prepend context function name */
3838
#define LOG_FMT(x) "%s: " x, __func__
3939

40+
/**
41+
* @brief Control message data structure for internal use. Sent to control socket.
42+
*/
43+
struct httpd_ctrl_data {
44+
enum httpd_ctrl_msg {
45+
HTTPD_CTRL_SHUTDOWN,
46+
HTTPD_CTRL_WORK,
47+
HTTPD_CTRL_MAX,
48+
} hc_msg;
49+
httpd_work_fn_t hc_work;
50+
void *hc_work_arg;
51+
};
52+
4053
/**
4154
* @brief Thread related data for internal use
4255
*/

components/esp_http_server/src/httpd_main.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,6 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
134134
return ESP_FAIL;
135135
}
136136

137-
struct httpd_ctrl_data {
138-
enum httpd_ctrl_msg {
139-
HTTPD_CTRL_SHUTDOWN,
140-
HTTPD_CTRL_WORK,
141-
} hc_msg;
142-
httpd_work_fn_t hc_work;
143-
void *hc_work_arg;
144-
};
145-
146137
esp_err_t httpd_queue_work(httpd_handle_t handle, httpd_work_fn_t work, void *arg)
147138
{
148139
if (handle == NULL || work == NULL) {

components/esp_http_server/src/httpd_txrx.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <esp_http_server.h>
1313
#include "esp_httpd_priv.h"
1414
#include <netinet/tcp.h>
15+
#include "ctrl_sock.h"
1516

1617
static const char *TAG = "httpd_txrx";
1718

@@ -699,6 +700,11 @@ esp_err_t httpd_req_async_handler_complete(httpd_req_t *r)
699700
return ESP_ERR_INVALID_ARG;
700701
}
701702

703+
// Get server handle and control socket info before freeing the request
704+
struct httpd_data *hd = (struct httpd_data *) r->handle;
705+
int msg_fd = hd->msg_fd;
706+
int port = hd->config.ctrl_port;
707+
702708
struct httpd_req_aux *ra = r->aux;
703709
ra->sd->for_async_req = false;
704710
free(ra->scratch);
@@ -709,6 +715,18 @@ esp_err_t httpd_req_async_handler_complete(httpd_req_t *r)
709715
free(r->aux);
710716
free(r);
711717

718+
// Send a dummy control message(httpd_ctrl_data) to unblock the main HTTP server task from the select() call.
719+
// Since the current connection FD was marked as inactive for async requests, the main task
720+
// will now re-add this FD to its select() descriptor list. This ensures that subsequent requests
721+
// on the same FD are processed correctly
722+
struct httpd_ctrl_data msg = {.hc_msg = HTTPD_CTRL_MAX};
723+
int ret = cs_send_to_ctrl_sock(msg_fd, port, &msg, sizeof(msg));
724+
if (ret < 0) {
725+
ESP_LOGW(TAG, LOG_FMT("failed to send socket notification"));
726+
return ESP_FAIL;
727+
}
728+
729+
ESP_LOGD(TAG, LOG_FMT("socket notification sent"));
712730
return ESP_OK;
713731
}
714732

0 commit comments

Comments
 (0)