summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-08-10 13:52:38 +0000
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-08-10 13:52:38 +0000
commite18185c55f8d1b6d6efe1b6a35b4c8c7bd48754a (patch)
treef0944fff5d0918803b202eb40da58b9b942982c3
parenteb46a43bc014b1d5e151fc53996aef14c29fec55 (diff)
Moved thread abstraction to mhd_threads.h/mhd_threads.c,
minor bugs fixed.
-rw-r--r--configure.ac10
-rw-r--r--src/include/platform.h5
-rw-r--r--src/include/platform_interface.h35
-rw-r--r--src/include/w32functions.h13
-rw-r--r--src/microhttpd/Makefile.am3
-rw-r--r--src/microhttpd/daemon.c120
-rw-r--r--src/microhttpd/internal.h1
-rw-r--r--src/microhttpd/mhd_limits.h8
-rw-r--r--src/microhttpd/mhd_threads.c274
-rw-r--r--src/microhttpd/mhd_threads.h151
-rw-r--r--src/microhttpd/test_shutdown_select.c4
-rw-r--r--src/platform/w32functions.c36
-rw-r--r--w32/common/MHD_config.h3
-rw-r--r--w32/common/libmicrohttpd-files.vcxproj2
-rw-r--r--w32/common/libmicrohttpd-filters.vcxproj6
15 files changed, 481 insertions, 190 deletions
diff --git a/configure.ac b/configure.ac
index e5ea2590..b9918093 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,7 +247,11 @@ test "x$with_threads" = "xpthreads" && with_threads='posix'
# Check for posix threads support, regardless of configure parameters as
# posix threads are used in some tests even on W32.
-AX_PTHREAD([HAVE_POSIX_THREADS='yes'],[HAVE_POSIX_THREADS='no'])
+AX_PTHREAD(
+ [
+ HAVE_POSIX_THREADS='yes'
+ AC_DEFINE([[HAVE_PTHREAD_H]],[[1]],[Define to 1 if you have the <pthread.h> header file.])
+ ],[[HAVE_POSIX_THREADS='no']])
AM_CONDITIONAL([HAVE_POSIX_THREADS],[test "x$HAVE_POSIX_THREADS" = "xyes"])
HAVE_W32_THREADS='no'
@@ -418,10 +422,10 @@ if test "x$HAVE_POSIX_THREADS" = "xyes"; then
fi
# Check for headers that are ALWAYS required
-AC_CHECK_HEADERS([fcntl.h math.h errno.h limits.h stdio.h locale.h sys/stat.h sys/types.h pthread.h],,AC_MSG_ERROR([Compiling libmicrohttpd requires standard UNIX headers files]))
+AC_CHECK_HEADERS([fcntl.h math.h errno.h limits.h stdio.h locale.h sys/stat.h sys/types.h],,AC_MSG_ERROR([Compiling libmicrohttpd requires standard UNIX headers files]))
# Check for optional headers
-AC_CHECK_HEADERS([sys/types.h sys/time.h sys/msg.h netdb.h netinet/in.h netinet/tcp.h time.h sys/socket.h sys/mman.h arpa/inet.h sys/select.h search.h endian.h machine/endian.h sys/endian.h sys/param.h sys/machine.h sys/byteorder.h machine/param.h sys/isa_defs.h inttypes.h])
+AC_CHECK_HEADERS([sys/types.h sys/time.h sys/msg.h netdb.h netinet/in.h netinet/tcp.h time.h sys/socket.h sys/mman.h arpa/inet.h sys/select.h search.h endian.h machine/endian.h sys/endian.h sys/param.h sys/machine.h sys/byteorder.h machine/param.h sys/isa_defs.h inttypes.h stddef.h])
AM_CONDITIONAL([HAVE_TSEARCH], [test "x$ac_cv_header_search_h" = "xyes"])
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
diff --git a/src/include/platform.h b/src/include/platform.h
index ed09fc71..5ec2c16f 100644
--- a/src/include/platform.h
+++ b/src/include/platform.h
@@ -48,11 +48,6 @@
#include <fcntl.h>
#include <signal.h>
#include <stddef.h>
-#ifdef MHD_USE_POSIX_THREADS
-#undef HAVE_CONFIG_H
-#include <pthread.h>
-#define HAVE_CONFIG_H 1
-#endif /* MHD_USE_POSIX_THREADS */
/* different OSes have fd_set in
a broad range of header files;
diff --git a/src/include/platform_interface.h b/src/include/platform_interface.h
index eba7612b..13f54530 100644
--- a/src/include/platform_interface.h
+++ b/src/include/platform_interface.h
@@ -189,41 +189,6 @@ typedef int _MHD_socket_funcs_size;
#else
#define MHD_random_() MHD_W32_random_()
#endif
-
-#if defined(MHD_USE_POSIX_THREADS)
-typedef pthread_t MHD_thread_handle_;
-#elif defined(MHD_USE_W32_THREADS)
-#include <windows.h>
-typedef HANDLE MHD_thread_handle_;
-#else
-#error "No threading API is available."
-#endif
-
-#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
-
-#if defined(MHD_USE_POSIX_THREADS)
-/**
- * Wait until specified thread is ended
- * @param thread ID to watch
- * @return zero on success, nonzero on failure
- */
-#define MHD_join_thread_(thread) pthread_join((thread), NULL)
-#elif defined(MHD_USE_W32_THREADS)
-/**
- * Wait until specified thread is ended
- * Close thread handle on success
- * @param thread handle to watch
- * @return zero on success, nonzero on failure
- */
-#define MHD_join_thread_(thread) (WAIT_OBJECT_0 == WaitForSingleObject((thread), INFINITE) ? (CloseHandle((thread)), 0) : 1 )
-#endif
-
#if defined(MHD_USE_W32_THREADS)
#define MHD_W32_MUTEX_ 1
#include <windows.h>
diff --git a/src/include/w32functions.h b/src/include/w32functions.h
index 057a989e..508778c9 100644
--- a/src/include/w32functions.h
+++ b/src/include/w32functions.h
@@ -194,19 +194,6 @@ int MHD_W32_random_(void);
/* Emulate snprintf function on W32 */
int W32_snprintf(char *__restrict s, size_t n, const char *__restrict format, ...);
-#ifndef _MSC_FULL_VER
-/* Thread name available only for VC-compiler */
-static void W32_SetThreadName(const DWORD thread_id, const char *thread_name)
-{ }
-#else /* _MSC_FULL_VER */
-/**
- * Set thread name
- * @param thread_id ID of thread, -1 for current thread
- * @param thread_name name to set
- */
-void W32_SetThreadName(const DWORD thread_id, const char *thread_name);
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 6cc40a87..e4b173ca 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -67,6 +67,7 @@ libmicrohttpd_la_SOURCES = \
mhd_limits.h mhd_byteorder.h \
sysfdsetsize.c sysfdsetsize.h \
mhd_str.c mhd_str.h \
+ mhd_threads.c mhd_threads.h \
response.c response.h
libmicrohttpd_la_CPPFLAGS = \
$(AM_CPPFLAGS) $(MHD_LIB_CPPFLAGS) \
@@ -200,7 +201,7 @@ test_shutdown_select_LDADD = \
endif
test_shutdown_poll_SOURCES = \
- test_shutdown_select.c
+ test_shutdown_select.c mhd_threads.h
if USE_POSIX_THREADS
test_shutdown_poll_CFLAGS = \
$(AM_CFLAGS) $(PTHREAD_CFLAGS)
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index fd8754ce..f493d19d 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -25,6 +25,7 @@
* @author Christian Grothoff
*/
#include "platform.h"
+#include "mhd_threads.h"
#include "internal.h"
#include "response.h"
#include "connection.h"
@@ -61,7 +62,6 @@
#define WIN32_LEAN_AND_MEAN 1
#endif /* !WIN32_LEAN_AND_MEAN */
#include <windows.h>
-#include <process.h>
#endif
/**
@@ -1280,81 +1280,6 @@ send_param_adapter (struct MHD_Connection *connection,
/**
- * Signature of main function for a thread.
- *
- * @param cls closure argument for the function
- * @return termination code from the thread
- */
-typedef MHD_THRD_RTRN_TYPE_
-(MHD_THRD_CALL_SPEC_ *ThreadStartRoutine)(void *cls);
-
-
-/**
- * Create a thread and set the attributes according to our options.
- *
- * @param thread handle to initialize
- * @param daemon daemon with options
- * @param start_routine main function of thread
- * @param arg argument for start_routine
- * @return 0 on success
- */
-static int
-create_thread (MHD_thread_handle_ *thread,
- const struct MHD_Daemon *daemon,
- ThreadStartRoutine start_routine,
- void *arg)
-{
-#if defined(MHD_USE_POSIX_THREADS)
- pthread_attr_t attr;
- pthread_attr_t *pattr;
- int ret;
-
- if (0 != daemon->thread_stack_size)
- {
- if (0 != (ret = pthread_attr_init (&attr)))
- goto ERR;
- if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
- {
- pthread_attr_destroy (&attr);
- goto ERR;
- }
- pattr = &attr;
- }
- else
- {
- pattr = NULL;
- }
- ret = pthread_create (thread, pattr,
- start_routine, arg);
-#ifdef HAVE_PTHREAD_SETNAME_NP
- if (0 == ret)
- (void) pthread_setname_np (*thread, "libmicrohttpd");
-#endif /* HAVE_PTHREAD_SETNAME_NP */
- if (0 != daemon->thread_stack_size)
- pthread_attr_destroy (&attr);
- return ret;
- ERR:
-#ifdef HAVE_MESSAGES
- MHD_DLOG (daemon,
- "Failed to set thread stack size\n");
-#endif
- errno = EINVAL;
- return ret;
-#elif defined(MHD_USE_W32_THREADS)
- unsigned threadID;
- *thread = (HANDLE)_beginthreadex(NULL, (unsigned)daemon->thread_stack_size, start_routine,
- arg, 0, &threadID);
- if (NULL == (*thread))
- return errno;
-
- W32_SetThreadName(threadID, "libmicrohttpd");
-
- return 0;
-#endif
-}
-
-
-/**
* Add another client connection to the set of connections
* managed by MHD. This API is usually not needed (since
* MHD will accept inbound connections on the server socket).
@@ -1388,7 +1313,6 @@ internal_add_connection (struct MHD_Daemon *daemon,
int external_add)
{
struct MHD_Connection *connection;
- int res_thread_create;
unsigned int i;
int eno;
struct MHD_Daemon *worker;
@@ -1635,17 +1559,17 @@ internal_add_connection (struct MHD_Daemon *daemon,
/* attempt to create handler thread */
if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
{
- res_thread_create = create_thread (&connection->pid,
- daemon,
- &MHD_handle_connection,
- connection);
- if (0 != res_thread_create)
+ if (!MHD_create_named_thread_(&connection->pid,
+ "MHD-connection",
+ daemon->thread_stack_size,
+ &MHD_handle_connection,
+ connection))
{
eno = errno;
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,
"Failed to create a thread: %s\n",
- MHD_strerror_ (res_thread_create));
+ MHD_strerror_ (eno));
#endif
goto cleanup;
}
@@ -1723,9 +1647,7 @@ internal_add_connection (struct MHD_Daemon *daemon,
MHD_pool_destroy (connection->pool);
free (connection->addr);
free (connection);
-#if EINVAL
errno = eno;
-#endif
return MHD_NO;
}
@@ -2157,7 +2079,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
(MHD_NO == pos->thread_joined) )
{
- if (0 != MHD_join_thread_ (pos->pid))
+ if (!MHD_join_thread_ (pos->pid))
{
MHD_PANIC ("Failed to join a thread\n");
}
@@ -3765,7 +3687,6 @@ MHD_start_daemon_va (unsigned int flags,
const struct sockaddr *servaddr = NULL;
socklen_t addrlen;
unsigned int i;
- int res_thread_create;
int use_pipe;
#ifndef HAVE_INET6
@@ -4307,13 +4228,17 @@ MHD_start_daemon_va (unsigned int flags,
( (0 != (flags & MHD_USE_SELECT_INTERNALLY)) &&
(0 == daemon->worker_pool_size)) ) &&
(0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) &&
- (0 != (res_thread_create =
- create_thread (&daemon->pid, daemon, &MHD_select_thread, daemon))))
+ (!MHD_create_named_thread_ (&daemon->pid,
+ (flags & MHD_USE_THREAD_PER_CONNECTION) ?
+ "MHD-listen" : "MHD-single",
+ daemon->thread_stack_size,
+ &MHD_select_thread,
+ daemon) ) )
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,
"Failed to create listen thread: %s\n",
- MHD_strerror_ (res_thread_create));
+ MHD_strerror_ (errno));
#endif
(void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex);
(void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex);
@@ -4416,13 +4341,16 @@ MHD_start_daemon_va (unsigned int flags,
}
/* Spawn the worker thread */
- if (0 != (res_thread_create =
- create_thread (&d->pid, daemon, &MHD_select_thread, d)))
+ if (!MHD_create_named_thread_(&d->pid,
+ "MHD-worker",
+ daemon->thread_stack_size,
+ &MHD_select_thread,
+ d))
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,
"Failed to create pool thread: %s\n",
- MHD_strerror_ (res_thread_create));
+ MHD_strerror_ (errno));
#endif
/* Free memory for this worker; cleanup below handles
* all previously-created workers. */
@@ -4564,7 +4492,7 @@ close_all_connections (struct MHD_Daemon *daemon)
{
if (MHD_YES != pos->thread_joined)
{
- if (0 != MHD_join_thread_ (pos->pid))
+ if (!MHD_join_thread_ (pos->pid))
MHD_PANIC ("Failed to join a thread\n");
pos->thread_joined = MHD_YES;
/* The thread may have concurrently modified the DLL,
@@ -4690,7 +4618,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
if (1 != MHD_pipe_write_ (daemon->worker_pool[i].wpipe[1], "e", 1))
MHD_PANIC ("failed to signal shutdown via pipe");
}
- if (0 != MHD_join_thread_ (daemon->worker_pool[i].pid))
+ if (!MHD_join_thread_ (daemon->worker_pool[i].pid))
MHD_PANIC ("Failed to join a thread\n");
close_all_connections (&daemon->worker_pool[i]);
(void) MHD_mutex_destroy_ (&daemon->worker_pool[i].cleanup_connection_mutex);
@@ -4720,7 +4648,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
(0 == daemon->worker_pool_size) ) )
{
- if (0 != MHD_join_thread_ (daemon->pid))
+ if (!MHD_join_thread_ (daemon->pid))
{
MHD_PANIC ("Failed to join a thread\n");
}
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 5c6a8b5d..aef6f17a 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -43,6 +43,7 @@
/* for TCP_FASTOPEN */
#include <netinet/tcp.h>
#endif
+#include "mhd_threads.h"
/**
diff --git a/src/microhttpd/mhd_limits.h b/src/microhttpd/mhd_limits.h
index 264803b9..f0f0d577 100644
--- a/src/microhttpd/mhd_limits.h
+++ b/src/microhttpd/mhd_limits.h
@@ -32,6 +32,14 @@
#include <limits.h>
#endif /* HAVE_LIMITS_H */
+#ifndef UINT_MAX
+#ifdef __UINT_MAX__
+#define UINT_MAX __UINT_MAX__
+#else /* ! __UINT_MAX__ */
+#define UINT_MAX ((unsigned int) ~((unsigned int)0))
+#endif /* ! __UINT_MAX__ */
+#endif /* !UINT_MAX */
+
#ifndef LONG_MAX
#ifdef __LONG_MAX__
#define LONG_MAX __LONG_MAX__
diff --git a/src/microhttpd/mhd_threads.c b/src/microhttpd/mhd_threads.c
new file mode 100644
index 00000000..07da4960
--- /dev/null
+++ b/src/microhttpd/mhd_threads.c
@@ -0,0 +1,274 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2016 Karlson2k (Evgeny Grin)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file microhttpd/mhd_threads.c
+ * @brief Implementation for thread functions
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_threads.h"
+#ifdef MHD_USE_W32_THREADS
+#include "mhd_limits.h"
+#include <process.h>
+#endif
+#ifdef MHD_USE_THREAD_NAME_
+#include <stdlib.h>
+#endif /* MHD_USE_THREAD_NAME_ */
+#include <errno.h>
+
+
+
+#if defined(MHD_USE_POSIX_THREADS)
+typedef pthread_t MHD_thread_ID_;
+#elif defined(MHD_USE_W32_THREADS)
+typedef DWORD MHD_thread_ID_;
+#endif
+
+
+#ifndef MHD_USE_THREAD_NAME_
+
+#define MHD_set_thread_name_(t, n) (void)
+#define MHD_set_cur_thread_name_(n) (void)
+
+#else /* MHD_USE_THREAD_NAME_ */
+
+#if defined(MHD_USE_POSIX_THREADS)
+#ifdef HAVE_PTHREAD_SETNAME_NP
+/**
+ * Set thread name
+ * @param thread_id ID of thread
+ * @param thread_name name to set
+ * @return non-zero on success, zero otherwise
+ */
+static int MHD_set_thread_name_(const MHD_thread_ID_ thread_id, const char *thread_name)
+{
+ if (NULL == thread_name)
+ return 0;
+
+ return !pthread_setname_np (thread_id, thread_name);
+}
+
+/**
+ * Set current thread name
+ * @param n name to set
+ * @return non-zero on success, zero otherwise
+ */
+#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_(pthread_self(),(n))
+#endif /* HAVE_PTHREAD_SETNAME_NP */
+
+#elif defined(MHD_USE_W32_THREADS)
+#ifndef _MSC_FULL_VER
+/* Thread name available only for VC-compiler */
+#else /* _MSC_FULL_VER */
+/**
+ * Set thread name
+ * @param thread_id ID of thread, -1 for current thread
+ * @param thread_name name to set
+ * @return non-zero on success, zero otherwise
+ */
+static int MHD_set_thread_name_(const MHD_thread_ID_ thread_id, const char *thread_name)
+{
+ static const DWORD VC_SETNAME_EXC = 0x406D1388;
+#pragma pack(push,8)
+ struct thread_info_struct
+ {
+ DWORD type; /* Must be 0x1000. */
+ LPCSTR name; /* Pointer to name (in user address space). */
+ DWORD ID; /* Thread ID (-1 = caller thread). */
+ DWORD flags; /* Reserved for future use, must be zero. */
+ } thread_info;
+#pragma pack(pop)
+
+ if (NULL == thread_name)
+ return 0;
+
+ thread_info.type = 0x1000;
+ thread_info.name = thread_name;
+ thread_info.ID = thread_id;
+ thread_info.flags = 0;
+
+ __try
+ { /* This exception is intercepted by debugger */
+ RaiseException(VC_SETNAME_EXC, 0, sizeof(thread_info) / sizeof(ULONG_PTR), (ULONG_PTR*)&thread_info);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {}
+
+ return !0;
+}
+
+
+/**
+ * Set current thread name
+ * @param n name to set
+ * @return non-zero on success, zero otherwise
+ */
+#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_(-1,(n))
+#endif /* _MSC_FULL_VER */
+#endif /* MHD_USE_W32_THREADS */
+
+#endif /* MHD_USE_THREAD_NAME_ */
+
+
+/**
+ * Create a thread and set the attributes according to our options.
+ *
+ * @param thread handle to initialize
+ * @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_ *thread,
+ size_t stack_size,
+ MHD_THREAD_START_ROUTINE_ start_routine,
+ void *arg)
+{
+#if defined(MHD_USE_POSIX_THREADS)
+ int res;
+
+ if (0 != stack_size)
+ {
+ pthread_attr_t attr;
+ res = pthread_attr_init (&attr);
+ if (0 == res)
+ {
+ res = pthread_attr_setstacksize (&attr, stack_size);
+ if (0 == res)
+ res = pthread_create (thread, &attr,
+ start_routine, arg);
+ pthread_attr_destroy (&attr);
+ }
+ }
+ else
+ res = pthread_create (thread, NULL, start_routine, arg);
+
+ if (0 != res)
+ errno = res;
+
+ return !res;
+#elif defined(MHD_USE_W32_THREADS)
+#if SIZE_MAX != UINT_MAX
+ if (stack_size > UINT_MAX)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+#endif /* SIZE_MAX != UINT_MAX */
+
+ *thread = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, start_routine,
+ arg, 0, NULL);
+ if ((MHD_thread_handle_)-1 == (*thread))
+ return 0;
+
+ return !0;
+#endif
+}
+
+#ifdef MHD_USE_THREAD_NAME_
+
+struct MHD_named_helper_param_
+{
+ /**
+ * Real thread start routine
+ */
+ MHD_THREAD_START_ROUTINE_ start_routine;
+
+ /**
+ * Argument for thread start routine
+ */
+ void *arg;
+
+ /**
+ * Name for thread
+ */
+ const char *name;
+};
+
+static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
+named_thread_starter (void *data)
+{
+ struct MHD_named_helper_param_ * const param =
+ (struct MHD_named_helper_param_ *) data;
+ void * arg;
+ MHD_THREAD_START_ROUTINE_ thr_func;
+
+ if (NULL == data)
+ return (MHD_THRD_RTRN_TYPE_)0;
+
+ MHD_set_cur_thread_name_(param->name);
+
+ arg = param->arg;
+ thr_func = param->start_routine;
+ free(data);
+
+ return thr_func(arg);
+}
+
+
+
+/**
+ * Create a named thread and set the attributes according to our options.
+ *
+ * @param thread handle to initialize
+ * @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
+ * @param arg argument for start_routine
+ * @return non-zero on success; zero otherwise (with errno set)
+ */
+int
+MHD_create_named_thread_ (MHD_thread_handle_ *thread,
+ const char* thread_name,
+ size_t stack_size,
+ MHD_THREAD_START_ROUTINE_ start_routine,
+ void *arg)
+{
+ struct MHD_named_helper_param_ * param;
+
+ if (NULL == thread_name)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+ param = malloc(sizeof(struct MHD_named_helper_param_));
+ if (NULL == param)
+ return 0;
+
+ param->start_routine = start_routine;
+ param->arg = arg;
+ param->name = thread_name;
+
+ /* 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, stack_size, &named_thread_starter, (void*)param))
+ {
+ free(param);
+ return 0;
+ }
+
+ return !0;
+}
+
+#endif /* MHD_USE_THREAD_NAME_ */
diff --git a/src/microhttpd/mhd_threads.h b/src/microhttpd/mhd_threads.h
new file mode 100644
index 00000000..23f21a28
--- /dev/null
+++ b/src/microhttpd/mhd_threads.h
@@ -0,0 +1,151 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2016 Karlson2k (Evgeny Grin)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/**
+ * @file microhttpd/mhd_threads.h
+ * @brief Header for platform-independent threads abstraction
+ * @author Karlson2k (Evgeny Grin)
+ *
+ * Provides basic abstraction for threads.
+ * Any functions can be implemented as macro on some platforms
+ * unless explicitly marked otherwise.
+ * Any function argument can be skipped in macro, so avoid
+ * variable modification in function parameters.
+ *
+ * @warning Unlike pthread functions, most of functions return
+ * nonzero on success.
+ */
+
+#ifndef MHD_THREADS_H
+#define MHD_THREADS_H 1
+
+#include "mhd_options.h"
+#ifdef HAVE_STDDEF_H
+# include <stddef.h> /* for size_t */
+#else /* ! HAVE_STDDEF_H */
+# include <stdlib.h> /* for size_t */
+#endif /* ! HAVE_STDDEF_H */
+
+#if defined(MHD_USE_POSIX_THREADS)
+# undef HAVE_CONFIG_H
+# include <pthread.h>
+# define HAVE_CONFIG_H 1
+#elif defined(MHD_USE_W32_THREADS)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif /* !WIN32_LEAN_AND_MEAN */
+# include <windows.h>
+#else
+# error No threading API is available.
+#endif
+
+#ifndef MHD_NO_THREAD_NAMES
+# if defined(MHD_USE_POSIX_THREADS)
+# ifdef HAVE_PTHREAD_SETNAME_NP
+# define MHD_USE_THREAD_NAME_
+# endif /* HAVE_PTHREAD_SETNAME_NP */
+# elif defined(MHD_USE_W32_THREADS)
+# ifdef _MSC_FULL_VER
+ /* Thread names only available with VC compiler */
+# define MHD_USE_THREAD_NAME_
+# endif /* _MSC_FULL_VER */
+# endif
+#endif
+
+#if defined(MHD_USE_POSIX_THREADS)
+ typedef pthread_t MHD_thread_handle_;
+#elif defined(MHD_USE_W32_THREADS)
+ typedef HANDLE MHD_thread_handle_;
+#endif
+
+#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
+
+#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
+ */
+#define MHD_join_thread_(thread) (!pthread_join((thread), NULL))
+#elif defined(MHD_USE_W32_THREADS)
+/**
+ * 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_(thread) (WAIT_OBJECT_0 == WaitForSingleObject((thread), INFINITE) ? (CloseHandle((thread)), !0) : 0)
+#endif
+
+/**
+ * Signature of main function for a thread.
+ *
+ * @param cls closure argument for the function
+ * @return termination code from the thread
+ */
+typedef MHD_THRD_RTRN_TYPE_
+(MHD_THRD_CALL_SPEC_ *MHD_THREAD_START_ROUTINE_)(void *cls);
+
+
+/**
+ * Create a thread and set the attributes according to our options.
+ *
+ * If thread is created, thread handle must be freed by #MHD_join_thread_().
+ *
+ * @param thread handle to initialize
+ * @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
+ */
+int
+MHD_create_thread_ (MHD_thread_handle_ *thread,
+ size_t stack_size,
+ MHD_THREAD_START_ROUTINE_ start_routine,
+ void *arg);
+
+#ifndef MHD_USE_THREAD_NAME_
+#define MHD_create_named_thread_(t,n,s,r,a) MHD_create_thread_((t),(s),(r),(a))
+#else /* MHD_USE_THREAD_NAME_ */
+/**
+ * Create a named thread and set the attributes according to our options.
+ *
+ * @param thread handle to initialize
+ * @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
+ * @param arg argument for start_routine
+ * @return non-zero on success; zero otherwise
+ */
+int
+MHD_create_named_thread_ (MHD_thread_handle_ *thread,
+ const char* thread_name,
+ size_t stack_size,
+ MHD_THREAD_START_ROUTINE_ start_routine,
+ void *arg);
+
+#endif /* MHD_USE_THREAD_NAME_ */
+
+#endif /* ! MHD_THREADS_H */
diff --git a/src/microhttpd/test_shutdown_select.c b/src/microhttpd/test_shutdown_select.c
index df36b49c..e3aaa20f 100644
--- a/src/microhttpd/test_shutdown_select.c
+++ b/src/microhttpd/test_shutdown_select.c
@@ -77,6 +77,8 @@
#include <stdbool.h>
#endif /* HAVE_STDBOOL_H */
+#include "mhd_threads.h"
+
#ifndef SOMAXCONN
#define SOMAXCONN 511
#endif /* ! SOMAXCONN */
@@ -346,7 +348,7 @@ main (int argc, char *const *argv)
shutdown (listen_socket, SHUT_RDWR);
/* fprintf (stdout, "Waiting for thread to finish...\n"); */
- if (0 != MHD_join_thread_(sel_thrd))
+ if (!MHD_join_thread_(sel_thrd))
{
MHD_socket_close_(listen_socket);
fprintf (stderr, "Can't join select() thread\n");
diff --git a/src/platform/w32functions.c b/src/platform/w32functions.c
index 0feafa5b..4b1e2c1c 100644
--- a/src/platform/w32functions.c
+++ b/src/platform/w32functions.c
@@ -667,39 +667,3 @@ int W32_snprintf(char *__restrict s, size_t n, const char *__restrict format, ..
return ret;
}
-
-#ifdef _MSC_FULL_VER
-/**
- * Set thread name
- * @param thread_id ID of thread, -1 for current thread
- * @param thread_name name to set
- */
-void W32_SetThreadName(const DWORD thread_id, const char *thread_name)
-{
- static const DWORD VC_SETNAME_EXC = 0x406D1388;
-#pragma pack(push,8)
- struct thread_info_struct
- {
- DWORD type; /* Must be 0x1000. */
- LPCSTR name; /* Pointer to name (in user address space). */
- DWORD ID; /* Thread ID (-1=caller thread). */
- DWORD flags; /* Reserved for future use, must be zero. */
- } thread_info;
-#pragma pack(pop)
-
- if (NULL == thread_name)
- return;
-
- thread_info.type = 0x1000;
- thread_info.name = thread_name;
- thread_info.ID = thread_id;
- thread_info.flags = 0;
-
- __try
- { /* This exception is intercepted by debugger */
- RaiseException(VC_SETNAME_EXC, 0, sizeof(thread_info) / sizeof(ULONG_PTR), (ULONG_PTR*)&thread_info);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {}
-}
-#endif /* _MSC_FULL_VER */
diff --git a/w32/common/MHD_config.h b/w32/common/MHD_config.h
index d147e984..c9205115 100644
--- a/w32/common/MHD_config.h
+++ b/w32/common/MHD_config.h
@@ -144,6 +144,9 @@
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
/* *** Other useful staff *** */
diff --git a/w32/common/libmicrohttpd-files.vcxproj b/w32/common/libmicrohttpd-files.vcxproj
index 4535f006..be50c277 100644
--- a/w32/common/libmicrohttpd-files.vcxproj
+++ b/w32/common/libmicrohttpd-files.vcxproj
@@ -16,6 +16,7 @@
<ClCompile Include="$(MhdSrc)microhttpd\tsearch.c" />
<ClCompile Include="$(MhdSrc)microhttpd\sysfdsetsize.c" />
<ClCompile Include="$(MhdSrc)microhttpd\mhd_str.c" />
+ <ClCompile Include="$(MhdSrc)microhttpd\mhd_threads.c" />
<ClCompile Include="$(MhdSrc)platform\w32functions.c" />
</ItemGroup>
<ItemGroup>
@@ -37,6 +38,7 @@
<ClInclude Include="$(MhdSrc)microhttpd\tsearch.h" />
<ClInclude Include="$(MhdSrc)microhttpd\sysfdsetsize.h" />
<ClInclude Include="$(MhdSrc)microhttpd\mhd_str.h" />
+ <ClInclude Include="$(MhdSrc)microhttpd\mhd_threads.h" />
<ClInclude Include="$(MhdW32Common)MHD_config.h" />
</ItemGroup>
<ItemGroup>
diff --git a/w32/common/libmicrohttpd-filters.vcxproj b/w32/common/libmicrohttpd-filters.vcxproj
index d43683ce..85232458 100644
--- a/w32/common/libmicrohttpd-filters.vcxproj
+++ b/w32/common/libmicrohttpd-filters.vcxproj
@@ -130,6 +130,12 @@
<ClCompile Include="$(MhdSrc)microhttpd\mhd_str.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClInclude Include="$(MhdSrc)microhttpd\mhd_threads.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClCompile Include="$(MhdSrc)microhttpd\mhd_threads.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="$(MhdW32Common)microhttpd_dll_res_vc.rc">