libmicrohttpd

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

commit 977814e18a50b6bcbe18c14302494cf9e570a408
parent 580814314f09b8e73f7641264998320a9694a459
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Sun, 17 Sep 2023 19:16:39 +0300

Refactored threads support

Some platforms do not have any "invalid" value of thread handle/ID.
Added tracking of the thread initialisation on such platforms to
avoid accidental match with uninitialised value.

Diffstat:
Msrc/microhttpd/connection.c | 10+++++-----
Msrc/microhttpd/daemon.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/microhttpd/mhd_threads.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/microhttpd/mhd_threads.h | 454++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/microhttpd/response.c | 2+-
Msrc/microhttpd/test_shutdown_select.c | 2+-
6 files changed, 522 insertions(+), 113 deletions(-)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -1151,7 +1151,7 @@ MHD_connection_close_ (struct MHD_Connection *connection, mhd_assert (! connection->suspended); #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (connection->tid) ); + MHD_thread_handle_ID_is_current_thread_ (connection->tid) ); #endif /* MHD_USE_THREADS */ if ( (NULL != daemon->notify_completed) && (connection->rq.client_aware) ) @@ -1195,7 +1195,7 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); #endif /* MHD_USE_THREADS */ if (0 == (daemon->options & MHD_USE_TLS)) @@ -6249,7 +6249,7 @@ cleanup_connection (struct MHD_Connection *connection) struct MHD_Daemon *daemon = connection->daemon; #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (connection->tid) ); + MHD_thread_handle_ID_is_current_thread_ (connection->tid) ); mhd_assert (NULL == daemon->worker_pool); #endif /* MHD_USE_THREADS */ @@ -6456,7 +6456,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) enum MHD_Result ret; #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (connection->tid) ); + MHD_thread_handle_ID_is_current_thread_ (connection->tid) ); #endif /* MHD_USE_THREADS */ /* 'daemon' is not used if epoll is not available and asserts are disabled */ (void) daemon; /* Mute compiler warning */ @@ -7140,7 +7140,7 @@ MHD_queue_response (struct MHD_Connection *connection, #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) if ( (! connection->suspended) && (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) && - (! MHD_thread_ID_is_current_thread_ (connection->tid)) ) + (! MHD_thread_handle_ID_is_current_thread_ (connection->tid)) ) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -1171,6 +1171,13 @@ call_handlers (struct MHD_Connection *con, bool on_fasttrack = (con->state == MHD_CONNECTION_INIT); ret = MHD_YES; + mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_valid_ID_ (con->tid))); + mhd_assert ((0 != (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (! MHD_thread_handle_ID_is_valid_ID_ (con->tid))); + mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_current_thread_ (con->tid))); + #ifdef HTTPS_SUPPORT if (con->tls_read_ready) read_ready = true; @@ -1322,7 +1329,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (connection->tid) ); + MHD_thread_handle_ID_is_current_thread_ (connection->tid) ); #endif /* MHD_USE_THREADS */ if (daemon->shutdown) { @@ -1670,7 +1677,7 @@ thread_main_connection_upgrade (struct MHD_Connection *con) struct MHD_Daemon *daemon = con->daemon; mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (con->tid) ); + MHD_thread_handle_ID_is_current_thread_ (con->tid) ); /* Here, we need to bi-directionally forward until the application tells us that it is done with the socket; */ @@ -1896,7 +1903,7 @@ thread_main_handle_connection (void *data) const bool use_poll = 0; #endif /* ! HAVE_POLL */ bool was_suspended = false; - MHD_thread_init_ (&(con->tid)); + MHD_thread_handle_ID_set_current_thread_ID_ (&(con->tid)); while ( (! daemon->shutdown) && (MHD_CONNECTION_CLOSED != con->state) ) @@ -2524,6 +2531,9 @@ new_connection_prepare_ (struct MHD_Daemon *daemon, connection->sk_nonblck = non_blck; connection->is_nonip = sk_is_nonip; connection->sk_spipe_suppress = sk_spipe_supprs; +#ifdef MHD_USE_THREADS + MHD_thread_handle_ID_set_invalid_ (&connection->tid); +#endif /* MHD_USE_THREADS */ connection->daemon = daemon; connection->connection_timeout_ms = daemon->connection_timeout_ms; connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; @@ -2743,7 +2753,7 @@ new_connection_process_ (struct MHD_Daemon *daemon, /* Function manipulate connection and timeout DL-lists, * must be called only within daemon thread. */ mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); mhd_assert (NULL == daemon->worker_pool); #endif /* MHD_USE_THREADS */ @@ -3102,7 +3112,7 @@ internal_suspend_connection_ (struct MHD_Connection *connection) #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); #endif if (connection->resuming) @@ -3199,7 +3209,7 @@ MHD_suspend_connection (struct MHD_Connection *connection) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); #endif /* MHD_USE_THREADS */ if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) @@ -3323,7 +3333,7 @@ resume_suspended_connections (struct MHD_Daemon *daemon) #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) mhd_assert (NULL == daemon->worker_pool); mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); #endif ret = MHD_NO; @@ -3664,7 +3674,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); mhd_assert (NULL == daemon->worker_pool); #endif /* MHD_USE_THREADS */ @@ -3888,7 +3898,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) struct MHD_Connection *pos; #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); mhd_assert (NULL == daemon->worker_pool); MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); @@ -3902,7 +3912,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && (! pos->thread_joined) && - (! MHD_join_thread_tid_ (&pos->tid)) ) + (! MHD_thread_handle_ID_join_thread_ (pos->tid)) ) MHD_PANIC (_ ("Failed to join a thread.\n")); #endif #ifdef UPGRADE_SUPPORT @@ -4075,7 +4085,7 @@ MHD_get_timeout64 (struct MHD_Daemon *daemon, #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); #endif /* MHD_USE_THREADS */ if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) @@ -4340,6 +4350,13 @@ internal_run_from_select (struct MHD_Daemon *daemon, (fd_set *) _MHD_DROP_CONST (read_fd_set))) ) MHD_itc_clear_ (daemon->itc); + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid))); + mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid))); + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_current_thread_ (daemon->tid))); + /* Process externally added connection if any */ if (daemon->have_new) new_connections_list_process_ (daemon); @@ -4693,6 +4710,13 @@ MHD_poll_all (struct MHD_Daemon *daemon, struct MHD_UpgradeResponseHandle *urhn; #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid))); + mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid))); + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_current_thread_ (daemon->tid))); + if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) && (MHD_NO != resume_suspended_connections (daemon)) ) millisec = 0; @@ -4907,6 +4931,9 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon, int poll_itc_idx; MHD_socket ls; + mhd_assert (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)); + mhd_assert (MHD_thread_handle_ID_is_current_thread_ (daemon->tid)); + memset (&p, 0, sizeof (p)); @@ -5070,7 +5097,7 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); #endif /* MHD_USE_THREADS */ num_events = MAX_EVENTS; @@ -5209,6 +5236,13 @@ MHD_epoll (struct MHD_Daemon *daemon, #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ bool need_to_accept; + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid))); + mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid))); + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (MHD_thread_handle_ID_is_current_thread_ (daemon->tid))); + if (-1 == daemon->epoll_fd) return MHD_NO; /* we're down! */ if (daemon->shutdown) @@ -5569,6 +5603,8 @@ MHD_run_wait (struct MHD_Daemon *daemon, (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ) return MHD_NO; + mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)); + if (0 > millisec) millisec = -1; #ifdef HAVE_POLL @@ -5611,7 +5647,7 @@ close_connection (struct MHD_Connection *pos) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); mhd_assert (NULL == daemon->worker_pool); #endif /* MHD_USE_THREADS */ @@ -5665,7 +5701,7 @@ MHD_polling_thread (void *cls) int err; #endif /* HAVE_PTHREAD_SIGMASK */ - MHD_thread_init_ (&(daemon->tid)); + MHD_thread_handle_ID_set_current_thread_ID_ (&(daemon->tid)); #ifdef HAVE_PTHREAD_SIGMASK if ((0 == sigemptyset (&s_mask)) && (0 == sigaddset (&s_mask, SIGPIPE))) @@ -7173,6 +7209,9 @@ MHD_start_daemon_va (unsigned int flags, daemon->unescape_callback = &unescape_wrapper; daemon->connection_timeout_ms = 0; /* no timeout */ MHD_itc_set_invalid_ (daemon->itc); +#ifdef MHD_USE_THREADS + MHD_thread_handle_ID_set_invalid_ (&daemon->tid); +#endif /* MHD_USE_THREADS */ #ifdef SOMAXCONN daemon->listen_backlog_size = SOMAXCONN; #else /* !SOMAXCONN */ @@ -8175,7 +8214,7 @@ close_all_connections (struct MHD_Daemon *daemon) #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ - MHD_thread_ID_is_current_thread_ (daemon->tid) ); + MHD_thread_handle_ID_is_current_thread_ (daemon->tid) ); mhd_assert (NULL == daemon->worker_pool); #endif /* MHD_USE_THREADS */ mhd_assert (daemon->shutdown); @@ -8288,7 +8327,7 @@ close_all_connections (struct MHD_Daemon *daemon) * MHD_resume_connection() during finishing of "upgraded" * thread. */ MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); - if (! MHD_join_thread_tid_ (&pos->tid)) + if (! MHD_thread_handle_ID_join_thread_ (pos->tid)) MHD_PANIC (_ ("Failed to join a thread.\n")); pos->thread_joined = true; MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); @@ -8320,7 +8359,7 @@ close_all_connections (struct MHD_Daemon *daemon) if (! pos->thread_joined) { MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); - if (! MHD_join_thread_tid_ (&pos->tid)) + if (! MHD_thread_handle_ID_join_thread_ (pos->tid)) MHD_PANIC (_ ("Failed to join a thread.\n")); MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); pos->thread_joined = true; @@ -8380,6 +8419,14 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) return; if ( (daemon->shutdown) && (NULL == daemon->master) ) MHD_PANIC (_ ("MHD_stop_daemon() was called twice.")); + + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (NULL != daemon->worker_pool) || \ + (MHD_thread_handle_ID_is_valid_handle_ (daemon->tid))); + mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) && + (NULL == daemon->worker_pool)) || \ + (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid))); + /* Slave daemons must be stopped by master daemon. */ mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) ); @@ -8458,7 +8505,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) mhd_assert (false); /* Should never happen */ } - if (! MHD_join_thread_tid_ (&daemon->tid)) + if (! MHD_thread_handle_ID_join_thread_ (daemon->tid)) { MHD_PANIC (_ ("Failed to join a thread.\n")); } @@ -8556,6 +8603,14 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon, { if (NULL == daemon) return NULL; + + mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \ + (NULL != daemon->worker_pool) || \ + (MHD_thread_handle_ID_is_valid_handle_ (daemon->tid))); + mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) && + (NULL == daemon->worker_pool)) || \ + (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid))); + switch (info_type) { case MHD_DAEMON_INFO_KEY_SIZE: diff --git a/src/microhttpd/mhd_threads.c b/src/microhttpd/mhd_threads.c @@ -38,6 +38,7 @@ #endif /* HAVE_PTHREAD_NP_H */ #endif /* MHD_USE_THREAD_NAME_ */ #include <errno.h> +#include "mhd_assert.h" #ifndef MHD_USE_THREAD_NAME_ @@ -66,7 +67,7 @@ * @return non-zero on success, zero otherwise */ static int -MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, +MHD_set_thread_name_ (const MHD_thread_ID_native_ thread_id, const char *thread_name) { if (NULL == thread_name) @@ -122,7 +123,7 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, * @return non-zero on success, zero otherwise */ static int -MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, +MHD_set_thread_name_ (const MHD_thread_ID_native_ thread_id, const char *thread_name) { static const DWORD VC_SETNAME_EXC = 0x406D1388; @@ -164,7 +165,7 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, * @return non-zero on success, zero otherwise */ #define MHD_set_cur_thread_name_(n) \ - MHD_set_thread_name_ ((MHD_thread_ID_) -1,(n)) + MHD_set_thread_name_ ((MHD_thread_ID_native_) -1,(n)) #endif /* _MSC_FULL_VER */ #endif /* MHD_USE_W32_THREADS */ @@ -176,20 +177,29 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, * * If thread is created, thread handle must be freed by MHD_join_thread_(). * - * @param thread handle to initialize + * @param handle_id handle to initialise * @param stack_size size of stack for new thread, 0 for default * @param start_routine main function of thread * @param arg argument for start_routine * @return non-zero on success; zero otherwise (with errno set) */ int -MHD_create_thread_ (MHD_thread_handle_ID_ *thread, +MHD_create_thread_ (MHD_thread_handle_ID_ *handle_id, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, void *arg) { #if defined(MHD_USE_POSIX_THREADS) int res; +#if defined(MHD_thread_handle_ID_get_native_handle_ptr_) + pthread_t *const new_tid_ptr = + MHD_thread_handle_ID_get_native_handle_ptr_ (handle_id); +#else /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */ + pthread_t new_tid; + pthread_t *const new_tid_ptr = &new_tid; +#endif /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */ + + mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (*handle_id)); if (0 != stack_size) { @@ -200,7 +210,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread, res = pthread_attr_setstacksize (&attr, stack_size); if (0 == res) - res = pthread_create (&(thread->handle), + res = pthread_create (new_tid_ptr, &attr, start_routine, arg); @@ -208,18 +218,28 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread, } } else - res = pthread_create (&(thread->handle), + res = pthread_create (new_tid_ptr, NULL, start_routine, arg); if (0 != res) + { errno = res; + MHD_thread_handle_ID_set_invalid_ (handle_id); + } +#if ! defined(MHD_thread_handle_ID_get_native_handle_ptr_) + else + MHD_thread_handle_ID_set_native_handle_ (handle_id, new_tid); +#endif /* ! MHD_thread_handle_ID_set_current_thread_ID_ */ return ! res; #elif defined(MHD_USE_W32_THREADS) uintptr_t thr_handle; #if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_INT + + mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (*handle_id)); + if (stack_size > UINT_MAX) { errno = EINVAL; @@ -232,11 +252,13 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread, arg, 0, NULL); - thread->handle = (MHD_thread_handle_) thr_handle; - - if ((MHD_thread_handle_) 0 == thread->handle) + if ((MHD_thread_handle_native_) 0 == (MHD_thread_handle_native_) thr_handle) return 0; + MHD_thread_handle_ID_set_native_handle_ (handle_id, \ + (MHD_thread_handle_native_) \ + thr_handle); + return ! 0; #endif } @@ -291,7 +313,7 @@ named_thread_starter (void *data) /** * Create a named thread and set the attributes according to our options. * - * @param thread handle to initialize + * @param handle_id handle to initialise * @param thread_name name for new thread * @param stack_size size of stack for new thread, 0 for default * @param start_routine main function of thread @@ -299,7 +321,7 @@ named_thread_starter (void *data) * @return non-zero on success; zero otherwise (with errno set) */ int -MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, +MHD_create_named_thread_ (MHD_thread_handle_ID_ *handle_id, const char *thread_name, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, @@ -308,15 +330,22 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, #if defined(MHD_USE_THREAD_ATTR_SETNAME) int res; pthread_attr_t attr; +#if defined(MHD_thread_handle_ID_get_native_handle_ptr_) + pthread_t *const new_tid_ptr = + MHD_thread_handle_ID_get_native_handle_ptr_ (handle_id); +#else /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */ + pthread_t new_tid; + pthread_t *const new_tid_ptr = &new_tid; +#endif /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */ res = pthread_attr_init (&attr); if (0 == res) { #if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) - /* NetBSD use 3 arguments: second argument is string in printf-like format, - * third argument is single argument for printf; - * OSF1 use 3 arguments too, but last one always must be zero (NULL). - * MHD doesn't use '%' in thread names, so both form are used in same way. + /* NetBSD uses 3 arguments: second argument is string in printf-like format, + * third argument is single argument for printf; + * OSF1 uses 3 arguments too, but last one always must be zero (NULL). + * MHD doesn't use '%' in thread names, so both forms are used in same way. */ res = pthread_attr_setname_np (&attr, thread_name, @@ -331,14 +360,21 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, res = pthread_attr_setstacksize (&attr, stack_size); if (0 == res) - res = pthread_create (&(thread->handle), + res = pthread_create (new_tid_ptr, &attr, start_routine, arg); pthread_attr_destroy (&attr); } if (0 != res) + { errno = res; + MHD_thread_handle_ID_set_invalid_ (handle_id); + } +#if ! defined(MHD_thread_handle_ID_get_native_handle_ptr_) + else + MHD_thread_handle_ID_set_native_handle_ (handle_id, new_tid); +#endif /* ! MHD_thread_handle_ID_set_current_thread_ID_ */ return ! res; #else /* ! MHD_USE_THREAD_ATTR_SETNAME */ @@ -361,12 +397,16 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, /* Set thread name in thread itself to avoid problems with * threads which terminated before name is set in other thread. */ - if (! MHD_create_thread_ (thread, + if (! MHD_create_thread_ (handle_id, stack_size, &named_thread_starter, (void *) param)) { + int err_num; + + err_num = errno; free (param); + errno = err_num; return 0; } diff --git a/src/microhttpd/mhd_threads.h b/src/microhttpd/mhd_threads.h @@ -64,6 +64,14 @@ # error No threading API is available. #endif +#ifdef HAVE_STDBOOL_H +# include <stdbool.h> +#endif /* HAVE_STDBOOL_H */ + +#if defined(MHD_USE_POSIX_THREADS) && defined(MHD_USE_W32_THREADS) +# error Both MHD_USE_POSIX_THREADS and MHD_USE_W32_THREADS are defined +#endif /* MHD_USE_POSIX_THREADS && MHD_USE_W32_THREADS */ + #ifndef MHD_NO_THREAD_NAMES # if defined(MHD_USE_POSIX_THREADS) # if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \ @@ -82,26 +90,305 @@ # endif #endif +/* ** Thread handle - used to control the thread ** */ + #if defined(MHD_USE_POSIX_THREADS) -typedef pthread_t MHD_thread_handle_; +/** + * Wait until specified thread is ended and free thread handle on success. + * @param thread handle to watch + * @return nonzero on success, zero otherwise + */ +# define MHD_join_thread_(native_handle) \ + (! pthread_join ((native_handle), NULL)) #elif defined(MHD_USE_W32_THREADS) -typedef HANDLE MHD_thread_handle_; +/** + * Wait until specified thread is ended and free thread handle on success. + * @param thread handle to watch + * @return nonzero on success, zero otherwise + */ +# define MHD_join_thread_(native_handle) \ + ( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \ + (CloseHandle ( (native_handle)), ! 0) : 0 ) #endif #if defined(MHD_USE_POSIX_THREADS) -# define MHD_THRD_RTRN_TYPE_ void* -# define MHD_THRD_CALL_SPEC_ +/** + * The native type to control the thread from other threads + */ +typedef pthread_t MHD_thread_handle_native_; #elif defined(MHD_USE_W32_THREADS) -# define MHD_THRD_RTRN_TYPE_ unsigned -# define MHD_THRD_CALL_SPEC_ __stdcall +/** + * The native type to control the thread from other threads + */ +typedef HANDLE MHD_thread_handle_native_; #endif #if defined(MHD_USE_POSIX_THREADS) -typedef pthread_t MHD_thread_ID_; +# if defined(__gnu_linux__) || \ + (defined(__linux__) && defined(__GLIBC__)) +/* The next part of code is disabled because it relies on undocumented + behaviour. + It could be enabled for neglectable performance and size improvements. */ +# if 0 /* Disabled code */ +/** + * The native invalid value for native thread handle + */ +# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \ + ((MHD_thread_handle_native_) 0) +# endif /* Disabled code */ +# endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */ #elif defined(MHD_USE_W32_THREADS) -typedef DWORD MHD_thread_ID_; +/** + * The native invalid value for native thread handle + */ +# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \ + ((MHD_thread_handle_native_) NULL) +#endif /* MHD_USE_W32_THREADS */ + +#if ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) +/** + * Structure with thread handle and validity flag + */ +struct MHD_thread_handle_struct_ +{ + bool valid; /**< true if native handle is set */ + MHD_thread_handle_native_ native; /**< the native thread handle */ +}; +/** + * Type with thread handle that can be set to invalid value + */ +typedef struct MHD_thread_handle_struct_ MHD_thread_handle_; + +/** + * Set variable pointed by @a handle_ptr to invalid (unset) value + */ +# define MHD_thread_handle_set_invalid_(handle_ptr) \ + ((handle_ptr)->valid = false) +/** + * Set native handle in variable pointed by @a handle_ptr + * to @a native_val value + */ +# define MHD_thread_handle_set_native_(handle_ptr,native_val) \ + ((handle_ptr)->valid = true, (handle_ptr)->native = native_val) +/** + * Check whether native handle value is set in @a handle_var variable + */ +# define MHD_thread_handle_is_valid_(handle_var) \ + ((handle_var).valid) +/** + * Get native handle value from @a handle_var variable + */ +# define MHD_thread_handle_get_native_(handle_var) \ + ((handle_var).native) +#else /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */ +/** + * Type with thread handle that can be set to invalid value + */ +typedef MHD_thread_handle_native_ MHD_thread_handle_; + +/** + * Set variable pointed by @a handle_ptr to invalid (unset) value + */ +# define MHD_thread_handle_set_invalid_(handle_ptr) \ + ((*(handle_ptr)) = MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) +/** + * Set native handle in the variable pointed by @a handle_ptr + * to @a native_val value + */ +# define MHD_thread_handle_set_native_(handle_ptr,native_val) \ + ((*(handle_ptr)) = native_val) +/** + * Check whether native handle value is set in @a handle_var variable + */ +# define MHD_thread_handle_is_valid_(handle_var) \ + (MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ != handle_var) +/** + * Get native handle value from @a handle_var variable + */ +# define MHD_thread_handle_get_native_(handle_var) \ + (handle_var) +/** + * Get pointer to native handle stored the variable pointed by @a handle_ptr + * @note This macro could not available if direct manipulation of + * the native handle is not possible + */ +# define MHD_thread_handle_get_native_ptr_(handle_ptr) \ + (handle_ptr) +#endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */ + + +/* ** Thread ID - used to check threads match ** */ + +#if defined(MHD_USE_POSIX_THREADS) +/** + * The native type used to check whether current thread matches expected thread + */ +typedef pthread_t MHD_thread_ID_native_; + +/** + * Function to get the current thread native ID. + */ +# define MHD_thread_ID_native_current_ pthread_self + +/** + * Check whether two native thread IDs are equal. + * @return non-zero if equal, zero if not equal + */ +# define MHD_thread_ID_native_equal_(id1,id2) \ + (pthread_equal(id1,id2)) +#elif defined(MHD_USE_W32_THREADS) +/** + * The native type used to check whether current thread matches expected thread + */ +typedef DWORD MHD_thread_ID_native_; + +/** + * Function to get the current thread native ID. + */ +# define MHD_thread_ID_native_current_ GetCurrentThreadId + +/** + * Check whether two native thread IDs are equal. + * @return non-zero if equal, zero if not equal + */ +# define MHD_thread_ID_native_equal_(id1,id2) \ + ((id1) == (id2)) #endif +/** + * Check whether specified thread ID matches current thread. + * @param id the thread ID to match + * @return nonzero on match, zero otherwise + */ +#define MHD_thread_ID_native_is_current_thread_(id) \ + MHD_thread_ID_native_equal_(id, MHD_thread_ID_native_current_()) + + +#if defined(MHD_USE_POSIX_THREADS) +# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) +/** + * The native invalid value for native thread ID + */ +# define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \ + MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ +# endif /* MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ */ +#elif defined(MHD_USE_W32_THREADS) +/** + * The native invalid value for native thread ID + */ + # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \ + ((MHD_thread_ID_native_) 0) +#endif /* MHD_USE_W32_THREADS */ + +#if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) +/** + * Structure with thread id and validity flag + */ +struct MHD_thread_ID_struct_ +{ + bool valid; /**< true if native ID is set */ + MHD_thread_ID_native_ native; /**< the native thread ID */ +}; +/** + * Type with thread ID that can be set to invalid value + */ +typedef struct MHD_thread_ID_struct_ MHD_thread_ID_; + +/** + * Set variable pointed by @a ID_ptr to invalid (unset) value + */ +# define MHD_thread_ID_set_invalid_(ID_ptr) \ + ((ID_ptr)->valid = false) +/** + * Set native ID in variable pointed by @a ID_ptr + * to @a native_val value + */ +# define MHD_thread_ID_set_native_(ID_ptr,native_val) \ + ((ID_ptr)->valid = true, (ID_ptr)->native = native_val) +/** + * Check whether native ID value is set in @a ID_var variable + */ +# define MHD_thread_ID_is_valid_(ID_var) \ + ((ID_var).valid) +/** + * Get native ID value from @a ID_var variable + */ +# define MHD_thread_ID_get_native_(ID_var) \ + ((ID_var).native) +/** + * Check whether @a ID_var variable is equal current thread + */ +# define MHD_thread_ID_is_current_thread_(ID_var) \ + (MHD_thread_ID_is_valid_(ID_var) && \ + MHD_thread_ID_native_is_current_thread_((ID_var).native)) +#else /* MHD_THREAD_ID_NATIVE_INVALID_ */ +/** + * Type with thread ID that can be set to invalid value + */ +typedef MHD_thread_ID_native_ MHD_thread_ID_; + +/** + * Set variable pointed by @a ID_ptr to invalid (unset) value + */ +# define MHD_thread_ID_set_invalid_(ID_ptr) \ + ((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_) +/** + * Set native ID in variable pointed by @a ID_ptr + * to @a native_val value + */ +# define MHD_thread_ID_set_native_(ID_ptr,native_val) \ + ((*(ID_ptr)) = native_val) +/** + * Check whether native ID value is set in @a ID_var variable + */ +# define MHD_thread_ID_is_valid_(ID_var) \ + (MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != ID_var) +/** + * Get native ID value from @a ID_var variable + */ +# define MHD_thread_ID_get_native_(ID_var) \ + (ID_var) +/** + * Check whether @a ID_var variable is equal current thread + */ +# define MHD_thread_ID_is_current_thread_(ID_var) \ + MHD_thread_ID_native_is_current_thread_(ID_var) +#endif /* MHD_THREAD_ID_NATIVE_INVALID_ */ + +/** + * Set current thread ID in variable pointed by @a ID_ptr + */ +# define MHD_thread_ID_set_current_thread_(ID_ptr) \ + MHD_thread_ID_set_native_(ID_ptr,MHD_thread_ID_native_current_()) + + +#if defined(MHD_USE_POSIX_THREADS) +# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \ + ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) +# error \ + MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined +# elif ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \ + defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) +# error \ + MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined +# endif +#endif /* MHD_USE_POSIX_THREADS */ + +/* When staring a new thread, the kernel (and thread implementation) may + * pause the calling (initial) thread and start the new thread. + * If thread identifier is assigned to variable in the initial thread then + * the value of the identifier variable will be undefined in the new thread + * until the initial thread continue processing. + * However, it is also possible that the new thread created, but not executed + * for some time while the initial thread continue execution. In this case any + * variable assigned in the new thread will be undefined for some time until + * they really processed by the new thread. + * To avoid data races, a special structure MHD_thread_handle_ID_ is used. + * The "handle" is assigned by calling (initial) thread and should be always + * defined when checked in the initial thread. + * The "ID" is assigned by the new thread and should be always defined when + * checked inside the new thread. + */ /* Depending on implementation, pthread_create() MAY set thread ID into * provided pointer and after it start thread OR start thread and after * it set thread ID. In the latter case, to avoid data races, additional @@ -109,95 +396,122 @@ typedef DWORD MHD_thread_ID_; * is known for setting thread ID BEFORE starting thread macro * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined * to save some resources. */ +/* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */ + /* * handle - must be valid when other thread knows that particular thread is started. * ID - must be valid when code is executed inside thread */ -#if defined(MHD_USE_POSIX_THREADS) -# ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD +#if defined(MHD_USE_POSIX_THREADS) && \ + defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \ + defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \ + defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \ + defined(MHD_thread_handle_get_native_ptr_) union _MHD_thread_handle_ID_ { MHD_thread_handle_ handle; /**< To be used in other threads */ - MHD_thread_ID_ ID; /**< To be used in thread itself */ + MHD_thread_ID_ ID; /**< To be used in the thread itself */ }; typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_; -# else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ -struct _MHD_thread_handle_ID_ -{ - MHD_thread_handle_ handle; /**< To be used in other threads */ - MHD_thread_ID_ ID; /**< To be used in thread itself */ -}; -typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; -# endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ -#elif defined(MHD_USE_W32_THREADS) +# define MHD_THREAD_HANDLE_ID_IS_UNION 1 +#else /* !MHD_USE_POSIX_THREADS + || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD + || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ + || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_ + || !MHD_thread_handle_get_native_ptr_ */ struct _MHD_thread_handle_ID_ { MHD_thread_handle_ handle; /**< To be used in other threads */ - MHD_thread_ID_ ID; /**< To be used in thread itself */ + MHD_thread_ID_ ID; /**< To be used in the thread itself */ }; typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; -#endif +#endif /* !MHD_USE_POSIX_THREADS + || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD + || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ + || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_ + || !MHD_thread_handle_get_native_ptr_ */ -#if defined(MHD_USE_POSIX_THREADS) /** - * Wait until specified thread is ended and free thread handle on success. - * @param thread handle to watch - * @return nonzero on success, zero otherwise + * Set MHD_thread_handle_ID_ to invalid value */ -#define MHD_join_thread_(thread) (! pthread_join ((thread), NULL)) -#elif defined(MHD_USE_W32_THREADS) +#define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr) \ + (MHD_thread_handle_set_invalid_(&((hndl_id_ptr)->handle)), \ + MHD_thread_ID_set_invalid_(&((hndl_id_ptr)->ID))) + /** - * Wait until specified thread is ended and free thread handle on success. - * @param thread handle to watch - * @return nonzero on success, zero otherwise + * Check whether thread handle is valid. + * To be used in threads other then the thread specified by @a hndl_id. */ -#define MHD_join_thread_(thread) \ - ( (WAIT_OBJECT_0 == WaitForSingleObject ( (thread), INFINITE)) ? \ - (CloseHandle ( (thread)), ! 0) : 0 ) -#endif +#define MHD_thread_handle_ID_is_valid_handle_(hndl_id) \ + MHD_thread_handle_is_valid_((hndl_id).handle) -#define MHD_join_thread_tid_(thread_handle_ID_ptr) \ - (MHD_join_thread_((thread_handle_ID_ptr)->handle)) +/** + * Set native handle in variable pointed by @a hndl_id_ptr + * to @a native_val value + */ +#define MHD_thread_handle_ID_set_native_handle_(hndl_id_ptr,native_val) \ + MHD_thread_handle_set_native_(&((hndl_id_ptr)->handle),native_val) -#if defined(MHD_USE_POSIX_THREADS) +#if defined(MHD_thread_handle_get_native_ptr_) /** - * Check whether provided thread ID matches current thread. - * @param ID thread ID to match - * @return nonzero on match, zero otherwise + * Get pointer to native handle stored the variable pointed by @a hndl_id_ptr + * @note This macro could not available if direct manipulation of + * the native handle is not possible */ -# define MHD_thread_ID_is_current_thread_(tid) \ - (pthread_equal ((tid).ID, pthread_self ())) -#elif defined(MHD_USE_W32_THREADS) +# define MHD_thread_handle_ID_get_native_handle_ptr_(hndl_id_ptr) \ + MHD_thread_handle_get_native_ptr_(&((hndl_id_ptr)->handle)) +#endif /* MHD_thread_handle_get_native_ptr_ */ + /** - * Check whether provided thread ID matches current thread. - * @param ID thread ID to match - * @return nonzero on match, zero otherwise + * Get native thread handle from MHD_thread_handle_ID_ variable. */ -# define MHD_thread_ID_is_current_thread_(tid) \ - (GetCurrentThreadId () == (tid).ID) -#endif +#define MHD_thread_handle_ID_get_native_handle_(hndl_id) \ + MHD_thread_handle_get_native_((hndl_id).handle) -#if defined(MHD_USE_POSIX_THREADS) -# ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD /** - * Initialise thread ID. - * @param thread_handle_ID_ptr pointer to thread handle-ID + * Check whether thread ID is valid. + * To be used in the thread itself. + */ +#define MHD_thread_handle_ID_is_valid_ID_(hndl_id) \ + MHD_thread_ID_is_valid_((hndl_id).ID) + +#if defined(MHD_THREAD_HANDLE_ID_IS_UNION) +# if defined(MHD_USE_W32_THREADS) +# error MHD_thread_handle_ID_ cannot be a union with W32 threads +# endif /* MHD_USE_W32_THREADS */ +/** + * Set current thread ID in the variable pointed by @a hndl_id_ptr */ -#define MHD_thread_init_(thread_handle_ID_ptr) (void) 0 -# else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ +# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) (void) 0 +#else /* ! MHD_THREAD_HANDLE_ID_IS_UNION */ /** - * Initialise thread ID. - * @param thread_handle_ID_ptr pointer to thread handle-ID + * Set current thread ID in the variable pointed by @a hndl_id_ptr */ -#define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ - pthread_self ()) -# endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ -#elif defined(MHD_USE_W32_THREADS) +# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) \ + MHD_thread_ID_set_current_thread_(&((hndl_id_ptr)->ID)) +#endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */ + +/** + * Check whether provided thread ID matches current thread. + * @param ID thread ID to match + * @return nonzero on match, zero otherwise + */ +#define MHD_thread_handle_ID_is_current_thread_(hndl_id) \ + MHD_thread_ID_is_current_thread_((hndl_id).ID) + /** - * Initialise thread ID. - * @param thread_handle_ID_ptr pointer to thread handle-ID + * Wait until specified thread is ended and free thread handle on success. + * @param hndl_id_ handle with ID to watch + * @return nonzero on success, zero otherwise */ -#define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ - GetCurrentThreadId ()) +#define MHD_thread_handle_ID_join_thread_(hndl_id) \ + MHD_join_thread_(MHD_thread_handle_ID_get_native_handle_(hndl_id)) + +#if defined(MHD_USE_POSIX_THREADS) +# define MHD_THRD_RTRN_TYPE_ void* +# define MHD_THRD_CALL_SPEC_ +#elif defined(MHD_USE_W32_THREADS) +# define MHD_THRD_RTRN_TYPE_ unsigned +# define MHD_THRD_CALL_SPEC_ __stdcall #endif /** @@ -215,14 +529,14 @@ typedef MHD_THRD_RTRN_TYPE_ * * If thread is created, thread handle must be freed by MHD_join_thread_(). * - * @param thread handle to initialize + * @param handle_id handle to initialise * @param stack_size size of stack for new thread, 0 for default * @param start_routine main function of thread * @param arg argument for start_routine * @return non-zero on success; zero otherwise (with errno set) */ int -MHD_create_thread_ (MHD_thread_handle_ID_ *thread, +MHD_create_thread_ (MHD_thread_handle_ID_ *handle_id, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, void *arg); @@ -233,7 +547,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread, /** * Create a named thread and set the attributes according to our options. * - * @param thread handle to initialize + * @param handle_id handle to initialise * @param thread_name name for new thread * @param stack_size size of stack for new thread, 0 for default * @param start_routine main function of thread @@ -241,7 +555,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread, * @return non-zero on success; zero otherwise */ int -MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, +MHD_create_named_thread_ (MHD_thread_handle_ID_ *handle_id, const char *thread_name, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c @@ -1941,7 +1941,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response, #ifdef MHD_USE_THREADS mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ - MHD_thread_ID_is_current_thread_ (connection->tid) ); + MHD_thread_handle_ID_is_current_thread_ (connection->tid) ); #endif /* MHD_USE_THREADS */ /* "Upgrade" responses accepted only if MHD_ALLOW_UPGRADE is enabled */ diff --git a/src/microhttpd/test_shutdown_select.c b/src/microhttpd/test_shutdown_select.c @@ -322,7 +322,7 @@ main (int argc, char *const *argv) */ for (i = 0; i < 5 && result == 0; i++) { - MHD_thread_handle_ sel_thrd; + MHD_thread_handle_native_ sel_thrd; /* fprintf(stdout, "Creating, binding and listening socket...\n"); */ MHD_socket listen_socket = start_socket_listen (AF_INET); if (MHD_INVALID_SOCKET == listen_socket)