libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit 19cf5ce05e994a01845469f35d722bc831f7d06e
parent b60bb4f7422894dea02dbbf09842ce26858b01b4
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Mon, 29 Dec 2025 11:15:31 +0100

add new connection: moved check for the daemon limit earlier

Diffstat:
Msrc/mhd2/daemon_add_conn.c | 254+++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 125 insertions(+), 129 deletions(-)

diff --git a/src/mhd2/daemon_add_conn.c b/src/mhd2/daemon_add_conn.c @@ -53,9 +53,13 @@ #include "mhd_sys_options.h" -#include "mhd_assert.h" #include "sys_bool_type.h" #include "sys_base_types.h" + +#include "mhd_assert.h" +#include "mhd_unreachable.h" +#include "mhd_assume.h" + #include "sys_offsetof.h" #include "sys_sockets_types.h" #include "sys_sockets_headers.h" @@ -355,7 +359,6 @@ new_connection_prepare_ (struct MHD_Daemon *restrict daemon, } free (c); } - mhd_socket_close (client_socket); mhd_assert (MHD_SC_OK != ret); return ret; /* Failure exit point */ } @@ -395,119 +398,113 @@ new_connection_process_inner (struct MHD_Daemon *restrict daemon, res = MHD_SC_POOL_MEM_ALLOC_FAILURE; } else - { /* 'pool' creation succeed */ + { + /* 'pool' creation succeed */ - if (daemon->conns.block_new) - { /* Connections limit */ - mhd_LOG_MSG (daemon, MHD_SC_LIMIT_CONNECTIONS_REACHED, \ - "Server reached connection limit. " \ - "Closing inbound connection."); - res = MHD_SC_LIMIT_CONNECTIONS_REACHED; - } - else - { /* Have space for new connection */ - mhd_assert (daemon->conns.count < daemon->conns.cfg.count_limit); - daemon->conns.count++; - daemon->conns.block_new = - (daemon->conns.count >= daemon->conns.cfg.count_limit); - mhd_DLINKEDL_INS_LAST (&(daemon->conns), connection, all_conn); + mhd_assert (! daemon->conns.block_new); + mhd_assert (daemon->conns.count < daemon->conns.cfg.count_limit); + + daemon->conns.count++; + daemon->conns.block_new = + (daemon->conns.count >= daemon->conns.cfg.count_limit); + mhd_DLINKEDL_INS_LAST (&(daemon->conns), connection, all_conn); - mhd_conn_init_activity_timeout (connection, - daemon->conns.cfg.timeout_milsec); + mhd_conn_init_activity_timeout (connection, + daemon->conns.cfg.timeout_milsec); - connection_set_http_layer_init_state (connection); - connection_set_initial_state (connection); + connection_set_http_layer_init_state (connection); + connection_set_initial_state (connection); - notify_app_conn (daemon, connection, false); + notify_app_conn (daemon, connection, false); #ifdef MHD_SUPPORT_THREADS - if (mhd_DAEMON_TYPE_LISTEN_ONLY == daemon->threading.d_type) + if (mhd_DAEMON_TYPE_LISTEN_ONLY == daemon->threading.d_type) + { + mhd_assert ((mhd_POLL_TYPE_SELECT == daemon->events.poll_type) || \ + (mhd_POLL_TYPE_POLL == daemon->events.poll_type)); + if (! mhd_create_named_thread (&connection->tid, + "MHD-connection", + daemon->threading.cfg.stack_size, + &mhd_worker_connection, + connection)) { - mhd_assert ((mhd_POLL_TYPE_SELECT == daemon->events.poll_type) || \ - (mhd_POLL_TYPE_POLL == daemon->events.poll_type)); - if (! mhd_create_named_thread (&connection->tid, - "MHD-connection", - daemon->threading.cfg.stack_size, - &mhd_worker_connection, - connection)) - { #ifdef EAGAIN - if (EAGAIN == errno) - { - mhd_LOG_MSG (daemon, MHD_SC_CONNECTION_THREAD_SYS_LIMITS_REACHED, - "Failed to create a new thread because it would " - "have exceeded the system limit on the number of " - "threads or no system resources available."); - res = MHD_SC_CONNECTION_THREAD_SYS_LIMITS_REACHED; - } - else + if (EAGAIN == errno) + { + mhd_LOG_MSG (daemon, MHD_SC_CONNECTION_THREAD_SYS_LIMITS_REACHED, + "Failed to create a new thread because it would " + "have exceeded the system limit on the number of " + "threads or no system resources available."); + res = MHD_SC_CONNECTION_THREAD_SYS_LIMITS_REACHED; + } + else #endif /* EAGAIN */ - if (1) - { - mhd_LOG_MSG (daemon, MHD_SC_CONNECTION_THREAD_LAUNCH_FAILURE, - "Failed to create a thread."); - res = MHD_SC_CONNECTION_THREAD_LAUNCH_FAILURE; - } + if (1) + { + mhd_LOG_MSG (daemon, MHD_SC_CONNECTION_THREAD_LAUNCH_FAILURE, + "Failed to create a thread."); + res = MHD_SC_CONNECTION_THREAD_LAUNCH_FAILURE; } - else /* New thread has been created successfully */ - return MHD_SC_OK; /* *** Function success exit point *** */ } - else + else /* New thread has been created successfully */ + return MHD_SC_OK; /* *** Function success exit point *** */ + } + else #else /* ! MHD_SUPPORT_THREADS */ - if (1) + if (1) #endif /* ! MHD_SUPPORT_THREADS */ - { /* No 'thread-per-connection' */ + { /* No 'thread-per-connection' */ #ifdef MHD_SUPPORT_THREADS - connection->tid = daemon->threading.tid; + connection->tid = daemon->threading.tid; #endif /* MHD_SUPPORT_THREADS */ #ifdef MHD_SUPPORT_EPOLL - if (mhd_POLL_TYPE_EPOLL == daemon->events.poll_type) + if (mhd_POLL_TYPE_EPOLL == daemon->events.poll_type) + { + struct epoll_event event; + + event.events = EPOLLIN | EPOLLOUT | EPOLLET; + event.data.ptr = connection; + if (0 != epoll_ctl (daemon->events.data.epoll.e_fd, + EPOLL_CTL_ADD, + connection->sk.fd, + &event)) { - struct epoll_event event; - - event.events = EPOLLIN | EPOLLOUT | EPOLLET; - event.data.ptr = connection; - if (0 != epoll_ctl (daemon->events.data.epoll.e_fd, - EPOLL_CTL_ADD, - connection->sk.fd, - &event)) - { - mhd_LOG_MSG (daemon, MHD_SC_EPOLL_CTL_ADD_FAILED, - "Failed to add connection socket to epoll."); - res = MHD_SC_EPOLL_CTL_ADD_FAILED; - } - else + mhd_LOG_MSG (daemon, MHD_SC_EPOLL_CTL_ADD_FAILED, + "Failed to add connection socket to epoll."); + res = MHD_SC_EPOLL_CTL_ADD_FAILED; + } + else + { + mhd_dbg_print_fd_mon_req ("conn", \ + connection->sk.fd, \ + true, \ + true, \ + false); + if (0) // TODO: implement turbo { - mhd_dbg_print_fd_mon_req ("conn", \ - connection->sk.fd, \ - true, \ - true, \ - false); - if (0) // TODO: implement turbo - { - connection->sk.ready = - (enum mhd_SocketNetState) (mhd_SOCKET_NET_STATE_RECV_READY - | mhd_SOCKET_NET_STATE_SEND_READY); - mhd_conn_mark_ready (connection, daemon); - } - return MHD_SC_OK; /* *** Function success exit point *** */ + connection->sk.ready = + (enum mhd_SocketNetState) (mhd_SOCKET_NET_STATE_RECV_READY + | mhd_SOCKET_NET_STATE_SEND_READY); + mhd_conn_mark_ready (connection, daemon); } + return MHD_SC_OK; /* *** Function success exit point *** */ } - else /* No 'epoll' */ -#endif /* MHD_SUPPORT_EPOLL */ - return MHD_SC_OK; /* *** Function success exit point *** */ } + else /* No 'epoll' */ +#endif /* MHD_SUPPORT_EPOLL */ + return MHD_SC_OK; /* *** Function success exit point *** */ + } - /* ** Below is a cleanup path ** */ - mhd_assert (MHD_SC_OK != res); - notify_app_conn (daemon, connection, true); + /* ** Below is a cleanup path ** */ + mhd_assert (MHD_SC_OK != res); + notify_app_conn (daemon, connection, true); - mhd_conn_deinit_activity_timeout (connection); + mhd_conn_deinit_activity_timeout (connection); + + mhd_DLINKEDL_DEL (&(daemon->conns), connection, all_conn); + daemon->conns.count--; + daemon->conns.block_new = false; - mhd_DLINKEDL_DEL (&(daemon->conns), connection, all_conn); - daemon->conns.count--; - daemon->conns.block_new = false; - } mhd_pool_destroy (connection->pool); } /* Free resources allocated before the call of this functions */ @@ -599,6 +596,8 @@ internal_add_connection (struct MHD_Daemon *daemon, mhd_assert (! mhd_D_HAS_WORKERS (daemon)); mhd_assert (mhd_FD_FITS_DAEMON (daemon, client_socket)); + res = MHD_SC_OK; + if ((! non_blck) && (mhd_POLL_TYPE_INT_IS_EPOLL (daemon->events.poll_type) || (mhd_WM_INT_EXTERNAL_EVENTS_EDGE == daemon->wmode_int))) @@ -606,50 +605,47 @@ internal_add_connection (struct MHD_Daemon *daemon, mhd_LOG_MSG (daemon, MHD_SC_NONBLOCKING_REQUIRED, \ "The daemon configuration requires non-blocking sockets, " "the new socket has not been added."); - (void) mhd_socket_close (client_socket); - return MHD_SC_NONBLOCKING_REQUIRED; + res = MHD_SC_NONBLOCKING_REQUIRED; } - res = new_connection_prepare_ (daemon, - client_socket, - addr, addrlen, - external_add, - non_blck, - sk_spipe_supprs, - sk_is_nonip, - &connection); - if (MHD_SC_OK != res) - return res; - - if (external_add) // TODO: support thread-unsafe + + if (MHD_SC_OK == res) { - mhd_assert (0 && "Not implemented yet"); -#if 1 // TODO: support externally added - return MHD_SC_FEATURE_DISABLED; -#else - /* Connection is added externally and MHD is thread safe mode. */ - MHD_mutex_lock_chk_ (&daemon->new_connections_mutex); - DLL_insert (daemon->new_connections_head, - daemon->new_connections_tail, - connection); - daemon->have_new = true; - MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex); - - /* The rest of connection processing must be handled in - * the daemon thread. */ - if ((mhd_ITC_IS_VALID (daemon->itc)) && - (! mhd_itc_activate (daemon->itc, "n"))) + if (daemon->conns.block_new) + { /* Connections limit */ + mhd_LOG_MSG (daemon, MHD_SC_LIMIT_CONNECTIONS_REACHED, \ + "Server reached connection limit. " \ + "Closing inbound connection."); + res = MHD_SC_LIMIT_CONNECTIONS_REACHED; + } + + if (MHD_SC_OK == res) { -#ifdef HAVE_MESSAGES - MHD_DLOG (daemon, - _ ("Failed to signal new connection via inter-thread " \ - "communication channel.\n")); -#endif + res = new_connection_prepare_ (daemon, + client_socket, + addr, addrlen, + external_add, + non_blck, + sk_spipe_supprs, + sk_is_nonip, + &connection); + + if (MHD_SC_OK == res) + { + mhd_ASSUME (NULL != connection); + + if (external_add) + res = MHD_SC_FEATURE_DISABLED; + else + return new_connection_process_ (daemon, connection); + } } - return MHD_YES; -#endif } - return new_connection_process_ (daemon, connection); + mhd_socket_close (client_socket); + + mhd_assert (MHD_SC_OK != res); + + return res; }