mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
thread-per-connection: improved timeout handling for 'poll()' mode, fixed short busy-waiting
* Avoid unneeded wake-ups * More precise timeout with milliseconds accuracy * Fixed potential short (less than one second) busy waiting when connection is about to expire.
This commit is contained in:
+2
-1
@@ -1438,7 +1438,9 @@ struct timeval test_var;
|
||||
AC_DEFINE_UNQUOTED([SIZEOF_STRUCT_TIMEVAL_TV_SEC], [$mhd_cv_size_timeval_tv_sec],
|
||||
[The size of `tv_sec' member of `struct timeval', as computed by sizeof])
|
||||
AC_CHECK_SIZEOF([uint64_t], [], [[#include <stdint.h>]])
|
||||
AC_CHECK_SIZEOF([int], [], [[#include <stdint.h>]])
|
||||
AC_CHECK_SIZEOF([unsigned int], [], [[#include <stdint.h>]])
|
||||
AC_CHECK_SIZEOF([unsigned long long], [], [[#include <stdint.h>]])
|
||||
AC_CHECK_SIZEOF([size_t], [],
|
||||
[[
|
||||
#ifdef HAVE_STDLIB_H
|
||||
@@ -1450,7 +1452,6 @@ AC_CHECK_SIZEOF([size_t], [],
|
||||
#include <stdio.h>
|
||||
]]
|
||||
)
|
||||
AC_CHECK_SIZEOF([unsigned long long], [], [[#include <stdint.h>]])
|
||||
|
||||
AC_CHECK_HEADERS([dlfcn.h],[have_tlsplugin=yes],[have_tlsplugin=no], [AC_INCLUDES_DEFAULT])
|
||||
AM_CONDITIONAL([MHD_HAVE_TLS_PLUGIN], [[test "x$have_tlsplugin" = xyes]])
|
||||
|
||||
+52
-38
@@ -1836,8 +1836,8 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
|
||||
* Get maximum wait period for the connection (the amount of time left before
|
||||
* connection time out)
|
||||
* @param c the connection to check
|
||||
* @return the maximum wait period before the connection must be processed
|
||||
* again.
|
||||
* @return the maximum number of millisecond before the connection must be
|
||||
* processed again.
|
||||
*/
|
||||
static uint64_t
|
||||
connection_get_wait (struct MHD_Connection *c)
|
||||
@@ -1897,8 +1897,6 @@ thread_main_handle_connection (void *data)
|
||||
fd_set ws;
|
||||
fd_set es;
|
||||
MHD_socket maxsock;
|
||||
struct timeval tv;
|
||||
struct timeval *tvp;
|
||||
#if WINDOWS
|
||||
#ifdef HAVE_POLL
|
||||
int extra_slot;
|
||||
@@ -1922,6 +1920,7 @@ thread_main_handle_connection (void *data)
|
||||
while ( (! daemon->shutdown) &&
|
||||
(MHD_CONNECTION_CLOSED != con->state) )
|
||||
{
|
||||
bool use_zero_timeout;
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
struct MHD_UpgradeResponseHandle *const urh = con->urh;
|
||||
#else /* ! UPGRADE_SUPPORT */
|
||||
@@ -1999,40 +1998,40 @@ thread_main_handle_connection (void *data)
|
||||
was_suspended = false;
|
||||
}
|
||||
|
||||
tvp = NULL;
|
||||
|
||||
if ( (MHD_EVENT_LOOP_INFO_BLOCK == con->event_loop_info)
|
||||
use_zero_timeout = ( (MHD_EVENT_LOOP_INFO_BLOCK == con->event_loop_info)
|
||||
#ifdef HTTPS_SUPPORT
|
||||
|| ( (con->tls_read_ready) &&
|
||||
(MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) )
|
||||
|| ( (con->tls_read_ready) && \
|
||||
(MHD_EVENT_LOOP_INFO_READ ==
|
||||
con->event_loop_info) )
|
||||
#endif /* HTTPS_SUPPORT */
|
||||
)
|
||||
{
|
||||
/* do not block: more data may be inside of TLS buffers waiting or
|
||||
* application must provide response data */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
if ( (NULL == tvp) &&
|
||||
(con->connection_timeout_ms > 0) )
|
||||
{
|
||||
const uint64_t mseconds_left = connection_get_wait (con);
|
||||
#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
|
||||
if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
|
||||
tv.tv_sec = TIMEVAL_TV_SEC_MAX;
|
||||
else
|
||||
#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
|
||||
tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
|
||||
|
||||
tv.tv_usec = (mseconds_left % 1000) * 1000;
|
||||
|
||||
tvp = &tv;
|
||||
}
|
||||
);
|
||||
if (! use_poll)
|
||||
{
|
||||
/* use select */
|
||||
bool err_state = false;
|
||||
struct timeval tv;
|
||||
struct timeval *tvp;
|
||||
if (use_zero_timeout)
|
||||
{
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
else if (con->connection_timeout_ms > 0)
|
||||
{
|
||||
const uint64_t mseconds_left = connection_get_wait (con);
|
||||
#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
|
||||
if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
|
||||
tv.tv_sec = TIMEVAL_TV_SEC_MAX;
|
||||
else
|
||||
#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
|
||||
tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
|
||||
|
||||
tv.tv_usec = ((uint16_t) (mseconds_left % 1000)) * 1000;
|
||||
tvp = &tv;
|
||||
}
|
||||
else
|
||||
tvp = NULL;
|
||||
|
||||
FD_ZERO (&rs);
|
||||
FD_ZERO (&ws);
|
||||
@@ -2124,7 +2123,22 @@ thread_main_handle_connection (void *data)
|
||||
#ifdef HAVE_POLL
|
||||
else
|
||||
{
|
||||
int timeout_val;
|
||||
/* use poll */
|
||||
if (use_zero_timeout)
|
||||
timeout_val = 0;
|
||||
else if (con->connection_timeout_ms > 0)
|
||||
{
|
||||
const uint64_t mseconds_left = connection_get_wait (con);
|
||||
#if SIZEOF_UINT64_T >= SIZEOF_INT
|
||||
if (mseconds_left >= INT_MAX)
|
||||
timeout_val = INT_MAX;
|
||||
else
|
||||
#endif /* SIZEOF_UINT64_T >= SIZEOF_INT */
|
||||
timeout_val = (int) mseconds_left;
|
||||
}
|
||||
else
|
||||
timeout_val = -1;
|
||||
memset (&p,
|
||||
0,
|
||||
sizeof (p));
|
||||
@@ -2160,7 +2174,7 @@ thread_main_handle_connection (void *data)
|
||||
#else
|
||||
1,
|
||||
#endif
|
||||
(NULL == tvp) ? -1 : (tv.tv_sec * 1000)) < 0)
|
||||
timeout_val) < 0)
|
||||
{
|
||||
if (MHD_SCKT_LAST_ERR_IS_ (MHD_SCKT_EINTR_))
|
||||
continue;
|
||||
@@ -4617,7 +4631,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
|
||||
p[poll_count].fd = ls;
|
||||
p[poll_count].events = POLLIN;
|
||||
p[poll_count].revents = 0;
|
||||
poll_listen = poll_count;
|
||||
poll_listen = (int) poll_count;
|
||||
poll_count++;
|
||||
}
|
||||
if (MHD_ITC_IS_VALID_ (daemon->itc))
|
||||
@@ -4625,7 +4639,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
|
||||
p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
|
||||
p[poll_count].events = POLLIN;
|
||||
p[poll_count].revents = 0;
|
||||
poll_itc_idx = poll_count;
|
||||
poll_itc_idx = (int) poll_count;
|
||||
poll_count++;
|
||||
}
|
||||
|
||||
@@ -4653,7 +4667,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
|
||||
#endif
|
||||
return MHD_NO;
|
||||
}
|
||||
if ( (-1 != poll_itc_idx) &&
|
||||
if ( (0 <= poll_itc_idx) &&
|
||||
(0 != (p[poll_itc_idx].revents & POLLIN)) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
|
||||
@@ -4665,7 +4679,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
|
||||
if (daemon->have_new)
|
||||
new_connections_list_process_ (daemon);
|
||||
|
||||
if ( (-1 != poll_listen) &&
|
||||
if ( (0 <= poll_listen) &&
|
||||
(0 != (p[poll_listen].revents & POLLIN)) )
|
||||
(void) MHD_accept_connection (daemon);
|
||||
return MHD_YES;
|
||||
@@ -6932,7 +6946,7 @@ MHD_start_daemon_va (unsigned int flags,
|
||||
}
|
||||
#endif
|
||||
if (listen (listen_fd,
|
||||
daemon->listen_backlog_size) < 0)
|
||||
(int) daemon->listen_backlog_size) < 0)
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
( (type) ((( ((type) 1) << (sizeof(type) * 8 - 2)) - 1) * 2 + 1) )
|
||||
#define MHD_TYPE_IS_SIGNED_(type) (((type) 0)>((type) - 1))
|
||||
|
||||
#ifndef INT_MAX
|
||||
#ifdef __INT_MAX__
|
||||
#define INT_MAX __INT_MAX__
|
||||
#else /* ! __UINT_MAX__ */
|
||||
#define INT_MAX MHD_SIGNED_TYPE_MAX_ (int)
|
||||
#endif /* ! __UINT_MAX__ */
|
||||
#endif /* !UINT_MAX */
|
||||
|
||||
#ifndef UINT_MAX
|
||||
#ifdef __UINT_MAX__
|
||||
#define UINT_MAX __UINT_MAX__
|
||||
|
||||
Reference in New Issue
Block a user