libmicrohttpd2

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

commit d5702562a9a9383960af7fea19984b826bc41079
parent a56fe4fa5782cc7c3994fdbb9c497d30fa36d945
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Sat, 27 Dec 2025 14:31:13 +0100

Corrected max wait time used for sockets polling

Diffstat:
Msrc/mhd2/events_process.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/mhd2/events_process.h | 2+-
2 files changed, 102 insertions(+), 31 deletions(-)

diff --git a/src/mhd2/events_process.c b/src/mhd2/events_process.c @@ -48,6 +48,8 @@ #include "mhd_assert.h" #include "mhd_unreachable.h" +#include "mhd_predict.h" + #if defined(mhd_DEBUG_SUSPEND_RESUME) || defined(mhd_DEBUG_POLLING_FDS) # include <stdio.h> #endif /* mhd_DEBUG_SUSPEND_RESUME */ @@ -321,16 +323,21 @@ daemon_resume_conns_if_needed (struct MHD_Daemon *restrict d) } +#if defined (MHD_SUPPORT_POLL) || defined(MHD_SUPPORT_EPOLL) + mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE static MHD_FN_PAR_NONNULL_ALL_ int -get_max_wait (struct MHD_Daemon *restrict d) +get_max_wait (const struct MHD_Daemon *restrict d) { - uint_fast64_t ui64_wait = mhd_daemon_get_wait_max (d); + const uint_fast64_t ui64_wait = mhd_daemon_get_wait_max (d); int i_wait = (int) ui64_wait; - if ((0 > i_wait) || - (ui64_wait != (uint_fast64_t) i_wait)) + if (MHD_WAIT_INDEFINITELY <= ui64_wait) + return -1; + + if (mhd_COND_ALMOST_NEVER ((0 > i_wait) || + (ui64_wait != (uint_fast64_t) i_wait))) return INT_MAX; return i_wait; @@ -340,6 +347,9 @@ get_max_wait (struct MHD_Daemon *restrict d) mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE /* End of warning-less data truncation */ +#endif +/* MHD_SUPPORT_POLL || MHD_SUPPORT_EPOLL */ + MHD_FN_PAR_NONNULL_ (1) static void update_conn_net_status (struct MHD_Daemon *restrict d, @@ -1130,6 +1140,61 @@ select_update_statuses_from_fdsets_and_resume_conn (struct MHD_Daemon *d, /** + * Get pointer to struct timeval for select() for polling daemon's sockets + * @param d the daemon to use + * @param[out] tmvl to pointer to the allocated struct timeval + * @return the @a tmvl pointer (with maximum wait value set) + * or NULL if select may wait indefinitely + */ +mhd_static_inline MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_OUT_ (2) struct timeval * +get_timeval_for_select (const struct MHD_Daemon *restrict d, + struct timeval *tmvl) +{ + const uint_fast64_t max_wait = mhd_daemon_get_wait_max (d); +#ifdef HAVE_TIME_T + time_t max_wait_secs = (time_t) (max_wait / 1000u); +#else /* ! HAVE_TIME_T */ + long max_wait_secs = (long) (max_wait / 1000u); +#endif /* ! HAVE_TIME_T */ +#ifdef HAVE_SUSECONDS_T + suseconds_t max_wait_usecs = (suseconds_t) ((max_wait % 1000u) * 1000u); +#else /* ! HAVE_SUSECONDS_T */ + long max_wait_usecs = (long) ((max_wait % 1000u) * 1000u); +#endif /* ! HAVE_SUSECONDS_T */ + + if (MHD_WAIT_INDEFINITELY <= max_wait) + return NULL; + + if (0u == max_wait) + { + tmvl->tv_sec = 0; + tmvl->tv_usec = 0; + + return tmvl; + } + + if (mhd_COND_ALMOST_NEVER ((max_wait / 1000u != + (uint_fast64_t) max_wait_secs) || + (max_wait_secs <= 0))) + { + /* Do not bother figuring out the real maximum 'time_t' value. + '0x7FFFFFFF' is large enough to be already unrealistic and should + fit most of signed or unsigned time_t types. */ + tmvl->tv_sec = 0x7FFFFFFF; + tmvl->tv_usec = 0; + + return tmvl; + } + + tmvl->tv_sec = max_wait_secs; + tmvl->tv_usec = max_wait_usecs; + + return tmvl; +} + + +/** * Update states of all connections, check for connection pending * to be accept()'ed, check for the events on ITC; resume connections * @param listen_only set to 'true' if connections's sockets should NOT @@ -1143,51 +1208,57 @@ get_all_net_updates_by_select_and_resume_conn (struct MHD_Daemon *restrict d, bool listen_only) { int max_socket; - int max_wait; - struct timeval tmvl; + struct timeval tmvl_value; + struct timeval *tmvl_ptr; int num_events; mhd_assert (mhd_POLL_TYPE_SELECT == d->events.poll_type); max_socket = select_update_fdsets (d, listen_only); - max_wait = get_max_wait (d); // TODO: use correct timeout value + tmvl_ptr = get_timeval_for_select (d, + &tmvl_value); #ifdef MHD_SOCKETS_KIND_WINSOCK if (0 == max_socket) { - Sleep ((unsigned int) max_wait); + Sleep (tmvl_ptr ? tmvl_ptr->tv_sec : 600); return true; } #endif /* MHD_SOCKETS_KIND_WINSOCK */ - tmvl.tv_sec = max_wait / 1000; -#ifndef MHD_SOCKETS_KIND_WINSOCK - tmvl.tv_usec = (uint_least16_t) ((max_wait % 1000) * 1000); -#else - tmvl.tv_usec = (int) ((max_wait % 1000) * 1000); -#endif - #ifdef mhd_DEBUG_POLLING_FDS - fprintf (stderr, - "### (Starting) select(%d, rfds, wfds, efds, [%llu, %llu])...\n", - max_socket + 1, - (unsigned long long) tmvl.tv_sec, - (unsigned long long) tmvl.tv_usec); + if (NULL != tmvl_ptr) + fprintf (stderr, + "### (Starting) select(%d, rfds, wfds, efds, [%llu, %llu])...\n", + max_socket + 1, + (unsigned long long) tmvl_ptr->tv_sec, + (unsigned long long) tmvl_ptr->tv_usec); + else + fprintf (stderr, + "### (Starting) select(%d, rfds, wfds, efds, [NULL])...\n", + max_socket + 1); #endif /* mhd_DEBUG_POLLING_FDS */ num_events = select (max_socket + 1, d->events.data.select.rfds, d->events.data.select.wfds, d->events.data.select.efds, - &tmvl); + tmvl_ptr); #ifdef mhd_DEBUG_POLLING_FDS - fprintf (stderr, - "### (Finished) select(%d, rfds, wfds, efds, ->[%llu, %llu]) -> " - "%d\n", - max_socket + 1, - (unsigned long long) tmvl.tv_sec, - (unsigned long long) tmvl.tv_usec, - num_events); + if (NULL != tmvl_ptr) + fprintf (stderr, + "### (Finished) select(%d, rfds, wfds, efds, ->[%llu, %llu]) -> " + "%d\n", + max_socket + 1, + (unsigned long long) tmvl_ptr->tv_sec, + (unsigned long long) tmvl_ptr->tv_usec, + num_events); + else + fprintf (stderr, + "### (Finished) select(%d, rfds, wfds, efds, [NULL]) -> " + "%d\n", + max_socket + 1, + num_events); #endif /* mhd_DEBUG_POLLING_FDS */ if (0 > num_events) @@ -1504,7 +1575,7 @@ get_all_net_updates_by_poll (struct MHD_Daemon *restrict d, num_fds = poll_update_fds (d, listen_only); // TODO: handle empty list situation - max_wait = get_max_wait (d); // TODO: use correct timeout value + max_wait = get_max_wait (d); #ifdef mhd_DEBUG_POLLING_FDS fprintf (stderr, @@ -1697,7 +1768,7 @@ get_all_net_updates_by_epoll (struct MHD_Daemon *restrict d) max_events = (int) d->events.data.epoll.num_elements; events_processed = 0; - max_wait = get_max_wait (d); // TODO: use correct timeout value + max_wait = get_max_wait (d); do { #ifdef mhd_DEBUG_POLLING_FDS diff --git a/src/mhd2/events_process.h b/src/mhd2/events_process.h @@ -87,7 +87,7 @@ mhd_worker_connection (void *cls); * #MHD_WAIT_INDEFINITELY if wait time is not limited */ MHD_INTERNAL uint_fast64_t -mhd_daemon_get_wait_max (struct MHD_Daemon *restrict d) +mhd_daemon_get_wait_max (const struct MHD_Daemon *restrict d) MHD_FN_PAR_NONNULL_ALL_; /**