libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit b05555f8372fd848698d87133d8ed194820ede1e
parent 38e2c1faacaf061c5a56de537e64eb86bdb4928f
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Tue, 21 Nov 2023 17:32:34 +0300

Added new daemon flag MHD_USE_NO_THREAD_SAFETY

Do not assume anymore single-threaded environment if external polling
is used.
The application is free to use multiple threads if MHD in the external
polling mode.
The new flag could be used to disable some thread-safety in MHD to
improve single-thread processing speed and resources usage. Basically
the new flag restores the old behaviour for external polling mode.

Diffstat:
Msrc/include/microhttpd.h | 16++++++++++++++--
Msrc/microhttpd/daemon.c | 29+++++++++++++++--------------
Msrc/microhttpd/internal.h | 11+++++++++++
3 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -96,7 +96,7 @@ extern "C" * they are parsed as decimal numbers. * Example: 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00097706 +#define MHD_VERSION 0x00097707 /* If generic headers don't work on your platform, include headers which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t', @@ -1531,7 +1531,19 @@ enum MHD_FLAG * Flag set to enable TLS 1.3 early data. This has * security implications, be VERY careful when using this. */ - MHD_USE_INSECURE_TLS_EARLY_DATA = 1U << 18 + MHD_USE_INSECURE_TLS_EARLY_DATA = 1U << 18, + + /** + * Indicates that MHD daemon will be used by application in single-threaded + * mode only. When this flag is set then application must call any MHD + * function only within a single thread. + * This flag turns off some internal thread-safety and allows MHD making + * some of the internal optimisations suitable only for single-threaded + * environment. + * Not compatible with #MHD_USE_INTERNAL_POLLING_THREAD. + * @note Available since #MHD_VERSION 0x00097707 + */ + MHD_USE_NO_THREAD_SAFETY = 1U << 19 }; diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -3152,9 +3152,9 @@ internal_add_connection (struct MHD_Daemon *daemon, return MHD_NO; if ((external_add) && - MHD_D_IS_USING_THREADS_ (daemon)) + MHD_D_IS_THREAD_SAFE_ (daemon)) { - /* Connection is added externally and MHD is handling its own threads. */ + /* 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, @@ -3186,7 +3186,7 @@ new_connections_list_process_ (struct MHD_Daemon *daemon) struct MHD_Connection *local_head; struct MHD_Connection *local_tail; mhd_assert (daemon->have_new); - mhd_assert (MHD_D_IS_USING_THREADS_ (daemon)); + mhd_assert (MHD_D_IS_THREAD_SAFE_ (daemon)); /* Detach DL-list of new connections from the daemon for * following local processing. */ @@ -3621,8 +3621,8 @@ MHD_add_connection (struct MHD_Daemon *daemon, bool sk_spipe_supprs; struct sockaddr_storage addrstorage; - /* NOT thread safe with internal thread. TODO: fix thread safety. */ - if ((! MHD_D_IS_USING_THREADS_ (daemon)) && + /* TODO: fix atomic value reading */ + if ((! MHD_D_IS_THREAD_SAFE_ (daemon)) && (daemon->connection_limit <= daemon->connections)) MHD_cleanup_connections (daemon); @@ -7667,7 +7667,12 @@ MHD_start_daemon_va (unsigned int flags, return NULL; #endif /* ! UPGRADE_SUPPORT */ } -#ifndef MHD_USE_THREADS +#ifdef MHD_USE_THREADS + if ((MHD_USE_NO_THREAD_SAFETY | MHD_USE_INTERNAL_POLLING_THREAD) == + ((MHD_USE_NO_THREAD_SAFETY | MHD_USE_INTERNAL_POLLING_THREAD) + & *pflags)) + return NULL; /* Cannot be thread-unsafe with multiple threads */ +#else /* ! MHD_USE_THREADS */ if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) return NULL; #endif /* ! MHD_USE_THREADS */ @@ -7707,9 +7712,9 @@ MHD_start_daemon_va (unsigned int flags, #endif } - if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) - *pflags = (*pflags & ~((enum MHD_FLAG) MHD_USE_ITC)); /* useless if we are using 'external' select */ - else + if (0 != (*pflags & MHD_USE_NO_THREAD_SAFETY)) + *pflags = (*pflags & ~((enum MHD_FLAG) MHD_USE_ITC)); /* useless in single-threaded environment */ + else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) { #ifdef HAVE_LISTEN_SHUTDOWN if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET)) @@ -9426,12 +9431,8 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon, return NULL; #endif /* ! EPOLL_SUPPORT */ case MHD_DAEMON_INFO_CURRENT_CONNECTIONS: - if (! MHD_D_IS_USING_THREADS_ (daemon)) - { - /* Assume that MHD_run() in not called in other thread - * at the same time. */ + if (! MHD_D_IS_THREAD_SAFE_ (daemon)) MHD_cleanup_connections (daemon); - } #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) else if (daemon->worker_pool) { diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -2551,6 +2551,12 @@ struct MHD_Daemon */ #define MHD_D_IS_USING_THREAD_PER_CONN_(d) \ (0 != ((d)->options & MHD_USE_THREAD_PER_CONNECTION)) + +/** + * Check whether the @a d daemon has thread-safety enabled. + */ +#define MHD_D_IS_THREAD_SAFE_(d) \ + (0 == ((d)->options & MHD_USE_NO_THREAD_SAFETY)) #else /* ! MHD_USE_THREADS */ /** * Checks whether the @a d daemon is using internal polling thread @@ -2560,6 +2566,11 @@ struct MHD_Daemon * Checks whether the @a d daemon is using thread-per-connection mode */ #define MHD_D_IS_USING_THREAD_PER_CONN_(d) ((void) d, 0) + +/** + * Check whether the @a d daemon has thread-safety enabled. + */ +#define MHD_D_IS_THREAD_SAFE_(d) ((void) d, 0) #endif /* ! MHD_USE_THREADS */ #ifdef HAS_FD_SETSIZE_OVERRIDABLE