aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2023-09-17 19:16:39 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2023-09-17 19:57:56 +0300
commit977814e18a50b6bcbe18c14302494cf9e570a408 (patch)
tree62911975077037841a47176723343153f23cda61
parent580814314f09b8e73f7641264998320a9694a459 (diff)
downloadlibmicrohttpd-977814e18a50b6bcbe18c14302494cf9e570a408.tar.gz
libmicrohttpd-977814e18a50b6bcbe18c14302494cf9e570a408.zip
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.
-rw-r--r--src/microhttpd/connection.c10
-rw-r--r--src/microhttpd/daemon.c91
-rw-r--r--src/microhttpd/mhd_threads.c76
-rw-r--r--src/microhttpd/mhd_threads.h454
-rw-r--r--src/microhttpd/response.c2
-rw-r--r--src/microhttpd/test_shutdown_select.c2
6 files changed, 522 insertions, 113 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 35dd96ab..b1872517 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1151,7 +1151,7 @@ MHD_connection_close_ (struct MHD_Connection *connection,
1151 mhd_assert (! connection->suspended); 1151 mhd_assert (! connection->suspended);
1152#ifdef MHD_USE_THREADS 1152#ifdef MHD_USE_THREADS
1153 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 1153 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1154 MHD_thread_ID_is_current_thread_ (connection->tid) ); 1154 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
1155#endif /* MHD_USE_THREADS */ 1155#endif /* MHD_USE_THREADS */
1156 if ( (NULL != daemon->notify_completed) && 1156 if ( (NULL != daemon->notify_completed) &&
1157 (connection->rq.client_aware) ) 1157 (connection->rq.client_aware) )
@@ -1195,7 +1195,7 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection)
1195#ifdef MHD_USE_THREADS 1195#ifdef MHD_USE_THREADS
1196 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 1196 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1197 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ 1197 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
1198 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 1198 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
1199#endif /* MHD_USE_THREADS */ 1199#endif /* MHD_USE_THREADS */
1200 1200
1201 if (0 == (daemon->options & MHD_USE_TLS)) 1201 if (0 == (daemon->options & MHD_USE_TLS))
@@ -6249,7 +6249,7 @@ cleanup_connection (struct MHD_Connection *connection)
6249 struct MHD_Daemon *daemon = connection->daemon; 6249 struct MHD_Daemon *daemon = connection->daemon;
6250#ifdef MHD_USE_THREADS 6250#ifdef MHD_USE_THREADS
6251 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 6251 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
6252 MHD_thread_ID_is_current_thread_ (connection->tid) ); 6252 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
6253 mhd_assert (NULL == daemon->worker_pool); 6253 mhd_assert (NULL == daemon->worker_pool);
6254#endif /* MHD_USE_THREADS */ 6254#endif /* MHD_USE_THREADS */
6255 6255
@@ -6456,7 +6456,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
6456 enum MHD_Result ret; 6456 enum MHD_Result ret;
6457#ifdef MHD_USE_THREADS 6457#ifdef MHD_USE_THREADS
6458 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 6458 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
6459 MHD_thread_ID_is_current_thread_ (connection->tid) ); 6459 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
6460#endif /* MHD_USE_THREADS */ 6460#endif /* MHD_USE_THREADS */
6461 /* 'daemon' is not used if epoll is not available and asserts are disabled */ 6461 /* 'daemon' is not used if epoll is not available and asserts are disabled */
6462 (void) daemon; /* Mute compiler warning */ 6462 (void) daemon; /* Mute compiler warning */
@@ -7140,7 +7140,7 @@ MHD_queue_response (struct MHD_Connection *connection,
7140#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 7140#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7141 if ( (! connection->suspended) && 7141 if ( (! connection->suspended) &&
7142 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) && 7142 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
7143 (! MHD_thread_ID_is_current_thread_ (connection->tid)) ) 7143 (! MHD_thread_handle_ID_is_current_thread_ (connection->tid)) )
7144 { 7144 {
7145#ifdef HAVE_MESSAGES 7145#ifdef HAVE_MESSAGES
7146 MHD_DLOG (daemon, 7146 MHD_DLOG (daemon,
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 209a6f86..09d58b8e 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -1171,6 +1171,13 @@ call_handlers (struct MHD_Connection *con,
1171 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT); 1171 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1172 ret = MHD_YES; 1172 ret = MHD_YES;
1173 1173
1174 mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1175 (MHD_thread_handle_ID_is_valid_ID_ (con->tid)));
1176 mhd_assert ((0 != (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1177 (! MHD_thread_handle_ID_is_valid_ID_ (con->tid)));
1178 mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1179 (MHD_thread_handle_ID_is_current_thread_ (con->tid)));
1180
1174#ifdef HTTPS_SUPPORT 1181#ifdef HTTPS_SUPPORT
1175 if (con->tls_read_ready) 1182 if (con->tls_read_ready)
1176 read_ready = true; 1183 read_ready = true;
@@ -1322,7 +1329,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1322 1329
1323#ifdef MHD_USE_THREADS 1330#ifdef MHD_USE_THREADS
1324 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 1331 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1325 MHD_thread_ID_is_current_thread_ (connection->tid) ); 1332 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
1326#endif /* MHD_USE_THREADS */ 1333#endif /* MHD_USE_THREADS */
1327 if (daemon->shutdown) 1334 if (daemon->shutdown)
1328 { 1335 {
@@ -1670,7 +1677,7 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1670 struct MHD_Daemon *daemon = con->daemon; 1677 struct MHD_Daemon *daemon = con->daemon;
1671 1678
1672 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 1679 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1673 MHD_thread_ID_is_current_thread_ (con->tid) ); 1680 MHD_thread_handle_ID_is_current_thread_ (con->tid) );
1674 /* Here, we need to bi-directionally forward 1681 /* Here, we need to bi-directionally forward
1675 until the application tells us that it is done 1682 until the application tells us that it is done
1676 with the socket; */ 1683 with the socket; */
@@ -1896,7 +1903,7 @@ thread_main_handle_connection (void *data)
1896 const bool use_poll = 0; 1903 const bool use_poll = 0;
1897#endif /* ! HAVE_POLL */ 1904#endif /* ! HAVE_POLL */
1898 bool was_suspended = false; 1905 bool was_suspended = false;
1899 MHD_thread_init_ (&(con->tid)); 1906 MHD_thread_handle_ID_set_current_thread_ID_ (&(con->tid));
1900 1907
1901 while ( (! daemon->shutdown) && 1908 while ( (! daemon->shutdown) &&
1902 (MHD_CONNECTION_CLOSED != con->state) ) 1909 (MHD_CONNECTION_CLOSED != con->state) )
@@ -2524,6 +2531,9 @@ new_connection_prepare_ (struct MHD_Daemon *daemon,
2524 connection->sk_nonblck = non_blck; 2531 connection->sk_nonblck = non_blck;
2525 connection->is_nonip = sk_is_nonip; 2532 connection->is_nonip = sk_is_nonip;
2526 connection->sk_spipe_suppress = sk_spipe_supprs; 2533 connection->sk_spipe_suppress = sk_spipe_supprs;
2534#ifdef MHD_USE_THREADS
2535 MHD_thread_handle_ID_set_invalid_ (&connection->tid);
2536#endif /* MHD_USE_THREADS */
2527 connection->daemon = daemon; 2537 connection->daemon = daemon;
2528 connection->connection_timeout_ms = daemon->connection_timeout_ms; 2538 connection->connection_timeout_ms = daemon->connection_timeout_ms;
2529 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; 2539 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
@@ -2743,7 +2753,7 @@ new_connection_process_ (struct MHD_Daemon *daemon,
2743 /* Function manipulate connection and timeout DL-lists, 2753 /* Function manipulate connection and timeout DL-lists,
2744 * must be called only within daemon thread. */ 2754 * must be called only within daemon thread. */
2745 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 2755 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
2746 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 2756 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
2747 mhd_assert (NULL == daemon->worker_pool); 2757 mhd_assert (NULL == daemon->worker_pool);
2748#endif /* MHD_USE_THREADS */ 2758#endif /* MHD_USE_THREADS */
2749 2759
@@ -3102,7 +3112,7 @@ internal_suspend_connection_ (struct MHD_Connection *connection)
3102#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3112#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3103 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 3113 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3104 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ 3114 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3105 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 3115 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
3106 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 3116 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3107#endif 3117#endif
3108 if (connection->resuming) 3118 if (connection->resuming)
@@ -3199,7 +3209,7 @@ MHD_suspend_connection (struct MHD_Connection *connection)
3199#ifdef MHD_USE_THREADS 3209#ifdef MHD_USE_THREADS
3200 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 3210 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3201 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ 3211 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3202 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 3212 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
3203#endif /* MHD_USE_THREADS */ 3213#endif /* MHD_USE_THREADS */
3204 3214
3205 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) 3215 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
@@ -3323,7 +3333,7 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
3323#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3333#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3324 mhd_assert (NULL == daemon->worker_pool); 3334 mhd_assert (NULL == daemon->worker_pool);
3325 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 3335 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3326 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 3336 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
3327#endif 3337#endif
3328 3338
3329 ret = MHD_NO; 3339 ret = MHD_NO;
@@ -3664,7 +3674,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
3664 3674
3665#ifdef MHD_USE_THREADS 3675#ifdef MHD_USE_THREADS
3666 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 3676 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3667 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 3677 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
3668 mhd_assert (NULL == daemon->worker_pool); 3678 mhd_assert (NULL == daemon->worker_pool);
3669#endif /* MHD_USE_THREADS */ 3679#endif /* MHD_USE_THREADS */
3670 3680
@@ -3888,7 +3898,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
3888 struct MHD_Connection *pos; 3898 struct MHD_Connection *pos;
3889#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3899#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3890 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 3900 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3891 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 3901 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
3892 mhd_assert (NULL == daemon->worker_pool); 3902 mhd_assert (NULL == daemon->worker_pool);
3893 3903
3894 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 3904 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
@@ -3902,7 +3912,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
3902 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); 3912 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3903 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) && 3913 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3904 (! pos->thread_joined) && 3914 (! pos->thread_joined) &&
3905 (! MHD_join_thread_tid_ (&pos->tid)) ) 3915 (! MHD_thread_handle_ID_join_thread_ (pos->tid)) )
3906 MHD_PANIC (_ ("Failed to join a thread.\n")); 3916 MHD_PANIC (_ ("Failed to join a thread.\n"));
3907#endif 3917#endif
3908#ifdef UPGRADE_SUPPORT 3918#ifdef UPGRADE_SUPPORT
@@ -4075,7 +4085,7 @@ MHD_get_timeout64 (struct MHD_Daemon *daemon,
4075 4085
4076#ifdef MHD_USE_THREADS 4086#ifdef MHD_USE_THREADS
4077 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 4087 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
4078 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 4088 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
4079#endif /* MHD_USE_THREADS */ 4089#endif /* MHD_USE_THREADS */
4080 4090
4081 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 4091 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
@@ -4340,6 +4350,13 @@ internal_run_from_select (struct MHD_Daemon *daemon,
4340 (fd_set *) _MHD_DROP_CONST (read_fd_set))) ) 4350 (fd_set *) _MHD_DROP_CONST (read_fd_set))) )
4341 MHD_itc_clear_ (daemon->itc); 4351 MHD_itc_clear_ (daemon->itc);
4342 4352
4353 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4354 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4355 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4356 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4357 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4358 (MHD_thread_handle_ID_is_current_thread_ (daemon->tid)));
4359
4343 /* Process externally added connection if any */ 4360 /* Process externally added connection if any */
4344 if (daemon->have_new) 4361 if (daemon->have_new)
4345 new_connections_list_process_ (daemon); 4362 new_connections_list_process_ (daemon);
@@ -4693,6 +4710,13 @@ MHD_poll_all (struct MHD_Daemon *daemon,
4693 struct MHD_UpgradeResponseHandle *urhn; 4710 struct MHD_UpgradeResponseHandle *urhn;
4694#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4711#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4695 4712
4713 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4714 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4715 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4716 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4717 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4718 (MHD_thread_handle_ID_is_current_thread_ (daemon->tid)));
4719
4696 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) && 4720 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4697 (MHD_NO != resume_suspended_connections (daemon)) ) 4721 (MHD_NO != resume_suspended_connections (daemon)) )
4698 millisec = 0; 4722 millisec = 0;
@@ -4907,6 +4931,9 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
4907 int poll_itc_idx; 4931 int poll_itc_idx;
4908 MHD_socket ls; 4932 MHD_socket ls;
4909 4933
4934 mhd_assert (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid));
4935 mhd_assert (MHD_thread_handle_ID_is_current_thread_ (daemon->tid));
4936
4910 memset (&p, 4937 memset (&p,
4911 0, 4938 0,
4912 sizeof (p)); 4939 sizeof (p));
@@ -5070,7 +5097,7 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
5070 5097
5071#ifdef MHD_USE_THREADS 5098#ifdef MHD_USE_THREADS
5072 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 5099 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
5073 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 5100 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
5074#endif /* MHD_USE_THREADS */ 5101#endif /* MHD_USE_THREADS */
5075 5102
5076 num_events = MAX_EVENTS; 5103 num_events = MAX_EVENTS;
@@ -5209,6 +5236,13 @@ MHD_epoll (struct MHD_Daemon *daemon,
5209#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 5236#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5210 bool need_to_accept; 5237 bool need_to_accept;
5211 5238
5239 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5240 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5241 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5242 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5243 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5244 (MHD_thread_handle_ID_is_current_thread_ (daemon->tid)));
5245
5212 if (-1 == daemon->epoll_fd) 5246 if (-1 == daemon->epoll_fd)
5213 return MHD_NO; /* we're down! */ 5247 return MHD_NO; /* we're down! */
5214 if (daemon->shutdown) 5248 if (daemon->shutdown)
@@ -5569,6 +5603,8 @@ MHD_run_wait (struct MHD_Daemon *daemon,
5569 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ) 5603 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5570 return MHD_NO; 5604 return MHD_NO;
5571 5605
5606 mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid));
5607
5572 if (0 > millisec) 5608 if (0 > millisec)
5573 millisec = -1; 5609 millisec = -1;
5574#ifdef HAVE_POLL 5610#ifdef HAVE_POLL
@@ -5611,7 +5647,7 @@ close_connection (struct MHD_Connection *pos)
5611 5647
5612#ifdef MHD_USE_THREADS 5648#ifdef MHD_USE_THREADS
5613 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 5649 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
5614 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 5650 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
5615 mhd_assert (NULL == daemon->worker_pool); 5651 mhd_assert (NULL == daemon->worker_pool);
5616#endif /* MHD_USE_THREADS */ 5652#endif /* MHD_USE_THREADS */
5617 5653
@@ -5665,7 +5701,7 @@ MHD_polling_thread (void *cls)
5665 int err; 5701 int err;
5666#endif /* HAVE_PTHREAD_SIGMASK */ 5702#endif /* HAVE_PTHREAD_SIGMASK */
5667 5703
5668 MHD_thread_init_ (&(daemon->tid)); 5704 MHD_thread_handle_ID_set_current_thread_ID_ (&(daemon->tid));
5669#ifdef HAVE_PTHREAD_SIGMASK 5705#ifdef HAVE_PTHREAD_SIGMASK
5670 if ((0 == sigemptyset (&s_mask)) && 5706 if ((0 == sigemptyset (&s_mask)) &&
5671 (0 == sigaddset (&s_mask, SIGPIPE))) 5707 (0 == sigaddset (&s_mask, SIGPIPE)))
@@ -7173,6 +7209,9 @@ MHD_start_daemon_va (unsigned int flags,
7173 daemon->unescape_callback = &unescape_wrapper; 7209 daemon->unescape_callback = &unescape_wrapper;
7174 daemon->connection_timeout_ms = 0; /* no timeout */ 7210 daemon->connection_timeout_ms = 0; /* no timeout */
7175 MHD_itc_set_invalid_ (daemon->itc); 7211 MHD_itc_set_invalid_ (daemon->itc);
7212#ifdef MHD_USE_THREADS
7213 MHD_thread_handle_ID_set_invalid_ (&daemon->tid);
7214#endif /* MHD_USE_THREADS */
7176#ifdef SOMAXCONN 7215#ifdef SOMAXCONN
7177 daemon->listen_backlog_size = SOMAXCONN; 7216 daemon->listen_backlog_size = SOMAXCONN;
7178#else /* !SOMAXCONN */ 7217#else /* !SOMAXCONN */
@@ -8175,7 +8214,7 @@ close_all_connections (struct MHD_Daemon *daemon)
8175#ifdef MHD_USE_THREADS 8214#ifdef MHD_USE_THREADS
8176 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 8215 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
8177 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \ 8216 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
8178 MHD_thread_ID_is_current_thread_ (daemon->tid) ); 8217 MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
8179 mhd_assert (NULL == daemon->worker_pool); 8218 mhd_assert (NULL == daemon->worker_pool);
8180#endif /* MHD_USE_THREADS */ 8219#endif /* MHD_USE_THREADS */
8181 mhd_assert (daemon->shutdown); 8220 mhd_assert (daemon->shutdown);
@@ -8288,7 +8327,7 @@ close_all_connections (struct MHD_Daemon *daemon)
8288 * MHD_resume_connection() during finishing of "upgraded" 8327 * MHD_resume_connection() during finishing of "upgraded"
8289 * thread. */ 8328 * thread. */
8290 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); 8329 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
8291 if (! MHD_join_thread_tid_ (&pos->tid)) 8330 if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
8292 MHD_PANIC (_ ("Failed to join a thread.\n")); 8331 MHD_PANIC (_ ("Failed to join a thread.\n"));
8293 pos->thread_joined = true; 8332 pos->thread_joined = true;
8294 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 8333 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
@@ -8320,7 +8359,7 @@ close_all_connections (struct MHD_Daemon *daemon)
8320 if (! pos->thread_joined) 8359 if (! pos->thread_joined)
8321 { 8360 {
8322 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); 8361 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
8323 if (! MHD_join_thread_tid_ (&pos->tid)) 8362 if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
8324 MHD_PANIC (_ ("Failed to join a thread.\n")); 8363 MHD_PANIC (_ ("Failed to join a thread.\n"));
8325 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 8364 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
8326 pos->thread_joined = true; 8365 pos->thread_joined = true;
@@ -8380,6 +8419,14 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
8380 return; 8419 return;
8381 if ( (daemon->shutdown) && (NULL == daemon->master) ) 8420 if ( (daemon->shutdown) && (NULL == daemon->master) )
8382 MHD_PANIC (_ ("MHD_stop_daemon() was called twice.")); 8421 MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
8422
8423 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
8424 (NULL != daemon->worker_pool) || \
8425 (MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
8426 mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
8427 (NULL == daemon->worker_pool)) || \
8428 (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
8429
8383 /* Slave daemons must be stopped by master daemon. */ 8430 /* Slave daemons must be stopped by master daemon. */
8384 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) ); 8431 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
8385 8432
@@ -8458,7 +8505,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
8458 mhd_assert (false); /* Should never happen */ 8505 mhd_assert (false); /* Should never happen */
8459 } 8506 }
8460 8507
8461 if (! MHD_join_thread_tid_ (&daemon->tid)) 8508 if (! MHD_thread_handle_ID_join_thread_ (daemon->tid))
8462 { 8509 {
8463 MHD_PANIC (_ ("Failed to join a thread.\n")); 8510 MHD_PANIC (_ ("Failed to join a thread.\n"));
8464 } 8511 }
@@ -8556,6 +8603,14 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon,
8556{ 8603{
8557 if (NULL == daemon) 8604 if (NULL == daemon)
8558 return NULL; 8605 return NULL;
8606
8607 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
8608 (NULL != daemon->worker_pool) || \
8609 (MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
8610 mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
8611 (NULL == daemon->worker_pool)) || \
8612 (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
8613
8559 switch (info_type) 8614 switch (info_type)
8560 { 8615 {
8561 case MHD_DAEMON_INFO_KEY_SIZE: 8616 case MHD_DAEMON_INFO_KEY_SIZE:
diff --git a/src/microhttpd/mhd_threads.c b/src/microhttpd/mhd_threads.c
index 13cccf4c..057bf376 100644
--- a/src/microhttpd/mhd_threads.c
+++ b/src/microhttpd/mhd_threads.c
@@ -38,6 +38,7 @@
38#endif /* HAVE_PTHREAD_NP_H */ 38#endif /* HAVE_PTHREAD_NP_H */
39#endif /* MHD_USE_THREAD_NAME_ */ 39#endif /* MHD_USE_THREAD_NAME_ */
40#include <errno.h> 40#include <errno.h>
41#include "mhd_assert.h"
41 42
42 43
43#ifndef MHD_USE_THREAD_NAME_ 44#ifndef MHD_USE_THREAD_NAME_
@@ -66,7 +67,7 @@
66 * @return non-zero on success, zero otherwise 67 * @return non-zero on success, zero otherwise
67 */ 68 */
68static int 69static int
69MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, 70MHD_set_thread_name_ (const MHD_thread_ID_native_ thread_id,
70 const char *thread_name) 71 const char *thread_name)
71{ 72{
72 if (NULL == thread_name) 73 if (NULL == thread_name)
@@ -122,7 +123,7 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
122 * @return non-zero on success, zero otherwise 123 * @return non-zero on success, zero otherwise
123 */ 124 */
124static int 125static int
125MHD_set_thread_name_ (const MHD_thread_ID_ thread_id, 126MHD_set_thread_name_ (const MHD_thread_ID_native_ thread_id,
126 const char *thread_name) 127 const char *thread_name)
127{ 128{
128 static const DWORD VC_SETNAME_EXC = 0x406D1388; 129 static const DWORD VC_SETNAME_EXC = 0x406D1388;
@@ -164,7 +165,7 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
164 * @return non-zero on success, zero otherwise 165 * @return non-zero on success, zero otherwise
165 */ 166 */
166#define MHD_set_cur_thread_name_(n) \ 167#define MHD_set_cur_thread_name_(n) \
167 MHD_set_thread_name_ ((MHD_thread_ID_) -1,(n)) 168 MHD_set_thread_name_ ((MHD_thread_ID_native_) -1,(n))
168#endif /* _MSC_FULL_VER */ 169#endif /* _MSC_FULL_VER */
169#endif /* MHD_USE_W32_THREADS */ 170#endif /* MHD_USE_W32_THREADS */
170 171
@@ -176,20 +177,29 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
176 * 177 *
177 * If thread is created, thread handle must be freed by MHD_join_thread_(). 178 * If thread is created, thread handle must be freed by MHD_join_thread_().
178 * 179 *
179 * @param thread handle to initialize 180 * @param handle_id handle to initialise
180 * @param stack_size size of stack for new thread, 0 for default 181 * @param stack_size size of stack for new thread, 0 for default
181 * @param start_routine main function of thread 182 * @param start_routine main function of thread
182 * @param arg argument for start_routine 183 * @param arg argument for start_routine
183 * @return non-zero on success; zero otherwise (with errno set) 184 * @return non-zero on success; zero otherwise (with errno set)
184 */ 185 */
185int 186int
186MHD_create_thread_ (MHD_thread_handle_ID_ *thread, 187MHD_create_thread_ (MHD_thread_handle_ID_ *handle_id,
187 size_t stack_size, 188 size_t stack_size,
188 MHD_THREAD_START_ROUTINE_ start_routine, 189 MHD_THREAD_START_ROUTINE_ start_routine,
189 void *arg) 190 void *arg)
190{ 191{
191#if defined(MHD_USE_POSIX_THREADS) 192#if defined(MHD_USE_POSIX_THREADS)
192 int res; 193 int res;
194#if defined(MHD_thread_handle_ID_get_native_handle_ptr_)
195 pthread_t *const new_tid_ptr =
196 MHD_thread_handle_ID_get_native_handle_ptr_ (handle_id);
197#else /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
198 pthread_t new_tid;
199 pthread_t *const new_tid_ptr = &new_tid;
200#endif /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
201
202 mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (*handle_id));
193 203
194 if (0 != stack_size) 204 if (0 != stack_size)
195 { 205 {
@@ -200,7 +210,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
200 res = pthread_attr_setstacksize (&attr, 210 res = pthread_attr_setstacksize (&attr,
201 stack_size); 211 stack_size);
202 if (0 == res) 212 if (0 == res)
203 res = pthread_create (&(thread->handle), 213 res = pthread_create (new_tid_ptr,
204 &attr, 214 &attr,
205 start_routine, 215 start_routine,
206 arg); 216 arg);
@@ -208,18 +218,28 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
208 } 218 }
209 } 219 }
210 else 220 else
211 res = pthread_create (&(thread->handle), 221 res = pthread_create (new_tid_ptr,
212 NULL, 222 NULL,
213 start_routine, 223 start_routine,
214 arg); 224 arg);
215 225
216 if (0 != res) 226 if (0 != res)
227 {
217 errno = res; 228 errno = res;
229 MHD_thread_handle_ID_set_invalid_ (handle_id);
230 }
231#if ! defined(MHD_thread_handle_ID_get_native_handle_ptr_)
232 else
233 MHD_thread_handle_ID_set_native_handle_ (handle_id, new_tid);
234#endif /* ! MHD_thread_handle_ID_set_current_thread_ID_ */
218 235
219 return ! res; 236 return ! res;
220#elif defined(MHD_USE_W32_THREADS) 237#elif defined(MHD_USE_W32_THREADS)
221 uintptr_t thr_handle; 238 uintptr_t thr_handle;
222#if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_INT 239#if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_INT
240
241 mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (*handle_id));
242
223 if (stack_size > UINT_MAX) 243 if (stack_size > UINT_MAX)
224 { 244 {
225 errno = EINVAL; 245 errno = EINVAL;
@@ -232,11 +252,13 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
232 arg, 252 arg,
233 0, 253 0,
234 NULL); 254 NULL);
235 thread->handle = (MHD_thread_handle_) thr_handle; 255 if ((MHD_thread_handle_native_) 0 == (MHD_thread_handle_native_) thr_handle)
236
237 if ((MHD_thread_handle_) 0 == thread->handle)
238 return 0; 256 return 0;
239 257
258 MHD_thread_handle_ID_set_native_handle_ (handle_id, \
259 (MHD_thread_handle_native_) \
260 thr_handle);
261
240 return ! 0; 262 return ! 0;
241#endif 263#endif
242} 264}
@@ -291,7 +313,7 @@ named_thread_starter (void *data)
291/** 313/**
292 * Create a named thread and set the attributes according to our options. 314 * Create a named thread and set the attributes according to our options.
293 * 315 *
294 * @param thread handle to initialize 316 * @param handle_id handle to initialise
295 * @param thread_name name for new thread 317 * @param thread_name name for new thread
296 * @param stack_size size of stack for new thread, 0 for default 318 * @param stack_size size of stack for new thread, 0 for default
297 * @param start_routine main function of thread 319 * @param start_routine main function of thread
@@ -299,7 +321,7 @@ named_thread_starter (void *data)
299 * @return non-zero on success; zero otherwise (with errno set) 321 * @return non-zero on success; zero otherwise (with errno set)
300 */ 322 */
301int 323int
302MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, 324MHD_create_named_thread_ (MHD_thread_handle_ID_ *handle_id,
303 const char *thread_name, 325 const char *thread_name,
304 size_t stack_size, 326 size_t stack_size,
305 MHD_THREAD_START_ROUTINE_ start_routine, 327 MHD_THREAD_START_ROUTINE_ start_routine,
@@ -308,15 +330,22 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
308#if defined(MHD_USE_THREAD_ATTR_SETNAME) 330#if defined(MHD_USE_THREAD_ATTR_SETNAME)
309 int res; 331 int res;
310 pthread_attr_t attr; 332 pthread_attr_t attr;
333#if defined(MHD_thread_handle_ID_get_native_handle_ptr_)
334 pthread_t *const new_tid_ptr =
335 MHD_thread_handle_ID_get_native_handle_ptr_ (handle_id);
336#else /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
337 pthread_t new_tid;
338 pthread_t *const new_tid_ptr = &new_tid;
339#endif /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
311 340
312 res = pthread_attr_init (&attr); 341 res = pthread_attr_init (&attr);
313 if (0 == res) 342 if (0 == res)
314 { 343 {
315#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) 344#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD)
316 /* NetBSD use 3 arguments: second argument is string in printf-like format, 345 /* NetBSD uses 3 arguments: second argument is string in printf-like format,
317 * third argument is single argument for printf; 346 * third argument is single argument for printf;
318 * OSF1 use 3 arguments too, but last one always must be zero (NULL). 347 * OSF1 uses 3 arguments too, but last one always must be zero (NULL).
319 * MHD doesn't use '%' in thread names, so both form are used in same way. 348 * MHD doesn't use '%' in thread names, so both forms are used in same way.
320 */ 349 */
321 res = pthread_attr_setname_np (&attr, 350 res = pthread_attr_setname_np (&attr,
322 thread_name, 351 thread_name,
@@ -331,14 +360,21 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
331 res = pthread_attr_setstacksize (&attr, 360 res = pthread_attr_setstacksize (&attr,
332 stack_size); 361 stack_size);
333 if (0 == res) 362 if (0 == res)
334 res = pthread_create (&(thread->handle), 363 res = pthread_create (new_tid_ptr,
335 &attr, 364 &attr,
336 start_routine, 365 start_routine,
337 arg); 366 arg);
338 pthread_attr_destroy (&attr); 367 pthread_attr_destroy (&attr);
339 } 368 }
340 if (0 != res) 369 if (0 != res)
370 {
341 errno = res; 371 errno = res;
372 MHD_thread_handle_ID_set_invalid_ (handle_id);
373 }
374#if ! defined(MHD_thread_handle_ID_get_native_handle_ptr_)
375 else
376 MHD_thread_handle_ID_set_native_handle_ (handle_id, new_tid);
377#endif /* ! MHD_thread_handle_ID_set_current_thread_ID_ */
342 378
343 return ! res; 379 return ! res;
344#else /* ! MHD_USE_THREAD_ATTR_SETNAME */ 380#else /* ! MHD_USE_THREAD_ATTR_SETNAME */
@@ -361,12 +397,16 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
361 /* Set thread name in thread itself to avoid problems with 397 /* Set thread name in thread itself to avoid problems with
362 * threads which terminated before name is set in other thread. 398 * threads which terminated before name is set in other thread.
363 */ 399 */
364 if (! MHD_create_thread_ (thread, 400 if (! MHD_create_thread_ (handle_id,
365 stack_size, 401 stack_size,
366 &named_thread_starter, 402 &named_thread_starter,
367 (void *) param)) 403 (void *) param))
368 { 404 {
405 int err_num;
406
407 err_num = errno;
369 free (param); 408 free (param);
409 errno = err_num;
370 return 0; 410 return 0;
371 } 411 }
372 412
diff --git a/src/microhttpd/mhd_threads.h b/src/microhttpd/mhd_threads.h
index 6e1dce32..9d9b19dd 100644
--- a/src/microhttpd/mhd_threads.h
+++ b/src/microhttpd/mhd_threads.h
@@ -64,6 +64,14 @@
64# error No threading API is available. 64# error No threading API is available.
65#endif 65#endif
66 66
67#ifdef HAVE_STDBOOL_H
68# include <stdbool.h>
69#endif /* HAVE_STDBOOL_H */
70
71#if defined(MHD_USE_POSIX_THREADS) && defined(MHD_USE_W32_THREADS)
72# error Both MHD_USE_POSIX_THREADS and MHD_USE_W32_THREADS are defined
73#endif /* MHD_USE_POSIX_THREADS && MHD_USE_W32_THREADS */
74
67#ifndef MHD_NO_THREAD_NAMES 75#ifndef MHD_NO_THREAD_NAMES
68# if defined(MHD_USE_POSIX_THREADS) 76# if defined(MHD_USE_POSIX_THREADS)
69# if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \ 77# if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
@@ -82,26 +90,305 @@
82# endif 90# endif
83#endif 91#endif
84 92
93/* ** Thread handle - used to control the thread ** */
94
85#if defined(MHD_USE_POSIX_THREADS) 95#if defined(MHD_USE_POSIX_THREADS)
86typedef pthread_t MHD_thread_handle_; 96/**
97 * Wait until specified thread is ended and free thread handle on success.
98 * @param thread handle to watch
99 * @return nonzero on success, zero otherwise
100 */
101# define MHD_join_thread_(native_handle) \
102 (! pthread_join ((native_handle), NULL))
87#elif defined(MHD_USE_W32_THREADS) 103#elif defined(MHD_USE_W32_THREADS)
88typedef HANDLE MHD_thread_handle_; 104/**
105 * Wait until specified thread is ended and free thread handle on success.
106 * @param thread handle to watch
107 * @return nonzero on success, zero otherwise
108 */
109# define MHD_join_thread_(native_handle) \
110 ( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \
111 (CloseHandle ( (native_handle)), ! 0) : 0 )
89#endif 112#endif
90 113
91#if defined(MHD_USE_POSIX_THREADS) 114#if defined(MHD_USE_POSIX_THREADS)
92# define MHD_THRD_RTRN_TYPE_ void* 115/**
93# define MHD_THRD_CALL_SPEC_ 116 * The native type to control the thread from other threads
117 */
118typedef pthread_t MHD_thread_handle_native_;
94#elif defined(MHD_USE_W32_THREADS) 119#elif defined(MHD_USE_W32_THREADS)
95# define MHD_THRD_RTRN_TYPE_ unsigned 120/**
96# define MHD_THRD_CALL_SPEC_ __stdcall 121 * The native type to control the thread from other threads
122 */
123typedef HANDLE MHD_thread_handle_native_;
97#endif 124#endif
98 125
99#if defined(MHD_USE_POSIX_THREADS) 126#if defined(MHD_USE_POSIX_THREADS)
100typedef pthread_t MHD_thread_ID_; 127# if defined(__gnu_linux__) || \
128 (defined(__linux__) && defined(__GLIBC__))
129/* The next part of code is disabled because it relies on undocumented
130 behaviour.
131 It could be enabled for neglectable performance and size improvements. */
132# if 0 /* Disabled code */
133/**
134 * The native invalid value for native thread handle
135 */
136# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
137 ((MHD_thread_handle_native_) 0)
138# endif /* Disabled code */
139# endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */
101#elif defined(MHD_USE_W32_THREADS) 140#elif defined(MHD_USE_W32_THREADS)
102typedef DWORD MHD_thread_ID_; 141/**
142 * The native invalid value for native thread handle
143 */
144# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
145 ((MHD_thread_handle_native_) NULL)
146#endif /* MHD_USE_W32_THREADS */
147
148#if ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
149/**
150 * Structure with thread handle and validity flag
151 */
152struct MHD_thread_handle_struct_
153{
154 bool valid; /**< true if native handle is set */
155 MHD_thread_handle_native_ native; /**< the native thread handle */
156};
157/**
158 * Type with thread handle that can be set to invalid value
159 */
160typedef struct MHD_thread_handle_struct_ MHD_thread_handle_;
161
162/**
163 * Set variable pointed by @a handle_ptr to invalid (unset) value
164 */
165# define MHD_thread_handle_set_invalid_(handle_ptr) \
166 ((handle_ptr)->valid = false)
167/**
168 * Set native handle in variable pointed by @a handle_ptr
169 * to @a native_val value
170 */
171# define MHD_thread_handle_set_native_(handle_ptr,native_val) \
172 ((handle_ptr)->valid = true, (handle_ptr)->native = native_val)
173/**
174 * Check whether native handle value is set in @a handle_var variable
175 */
176# define MHD_thread_handle_is_valid_(handle_var) \
177 ((handle_var).valid)
178/**
179 * Get native handle value from @a handle_var variable
180 */
181# define MHD_thread_handle_get_native_(handle_var) \
182 ((handle_var).native)
183#else /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
184/**
185 * Type with thread handle that can be set to invalid value
186 */
187typedef MHD_thread_handle_native_ MHD_thread_handle_;
188
189/**
190 * Set variable pointed by @a handle_ptr to invalid (unset) value
191 */
192# define MHD_thread_handle_set_invalid_(handle_ptr) \
193 ((*(handle_ptr)) = MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
194/**
195 * Set native handle in the variable pointed by @a handle_ptr
196 * to @a native_val value
197 */
198# define MHD_thread_handle_set_native_(handle_ptr,native_val) \
199 ((*(handle_ptr)) = native_val)
200/**
201 * Check whether native handle value is set in @a handle_var variable
202 */
203# define MHD_thread_handle_is_valid_(handle_var) \
204 (MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ != handle_var)
205/**
206 * Get native handle value from @a handle_var variable
207 */
208# define MHD_thread_handle_get_native_(handle_var) \
209 (handle_var)
210/**
211 * Get pointer to native handle stored the variable pointed by @a handle_ptr
212 * @note This macro could not available if direct manipulation of
213 * the native handle is not possible
214 */
215# define MHD_thread_handle_get_native_ptr_(handle_ptr) \
216 (handle_ptr)
217#endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
218
219
220/* ** Thread ID - used to check threads match ** */
221
222#if defined(MHD_USE_POSIX_THREADS)
223/**
224 * The native type used to check whether current thread matches expected thread
225 */
226typedef pthread_t MHD_thread_ID_native_;
227
228/**
229 * Function to get the current thread native ID.
230 */
231# define MHD_thread_ID_native_current_ pthread_self
232
233/**
234 * Check whether two native thread IDs are equal.
235 * @return non-zero if equal, zero if not equal
236 */
237# define MHD_thread_ID_native_equal_(id1,id2) \
238 (pthread_equal(id1,id2))
239#elif defined(MHD_USE_W32_THREADS)
240/**
241 * The native type used to check whether current thread matches expected thread
242 */
243typedef DWORD MHD_thread_ID_native_;
244
245/**
246 * Function to get the current thread native ID.
247 */
248# define MHD_thread_ID_native_current_ GetCurrentThreadId
249
250/**
251 * Check whether two native thread IDs are equal.
252 * @return non-zero if equal, zero if not equal
253 */
254# define MHD_thread_ID_native_equal_(id1,id2) \
255 ((id1) == (id2))
103#endif 256#endif
104 257
258/**
259 * Check whether specified thread ID matches current thread.
260 * @param id the thread ID to match
261 * @return nonzero on match, zero otherwise
262 */
263#define MHD_thread_ID_native_is_current_thread_(id) \
264 MHD_thread_ID_native_equal_(id, MHD_thread_ID_native_current_())
265
266
267#if defined(MHD_USE_POSIX_THREADS)
268# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
269/**
270 * The native invalid value for native thread ID
271 */
272# define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
273 MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
274# endif /* MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ */
275#elif defined(MHD_USE_W32_THREADS)
276/**
277 * The native invalid value for native thread ID
278 */
279 # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
280 ((MHD_thread_ID_native_) 0)
281#endif /* MHD_USE_W32_THREADS */
282
283#if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
284/**
285 * Structure with thread id and validity flag
286 */
287struct MHD_thread_ID_struct_
288{
289 bool valid; /**< true if native ID is set */
290 MHD_thread_ID_native_ native; /**< the native thread ID */
291};
292/**
293 * Type with thread ID that can be set to invalid value
294 */
295typedef struct MHD_thread_ID_struct_ MHD_thread_ID_;
296
297/**
298 * Set variable pointed by @a ID_ptr to invalid (unset) value
299 */
300# define MHD_thread_ID_set_invalid_(ID_ptr) \
301 ((ID_ptr)->valid = false)
302/**
303 * Set native ID in variable pointed by @a ID_ptr
304 * to @a native_val value
305 */
306# define MHD_thread_ID_set_native_(ID_ptr,native_val) \
307 ((ID_ptr)->valid = true, (ID_ptr)->native = native_val)
308/**
309 * Check whether native ID value is set in @a ID_var variable
310 */
311# define MHD_thread_ID_is_valid_(ID_var) \
312 ((ID_var).valid)
313/**
314 * Get native ID value from @a ID_var variable
315 */
316# define MHD_thread_ID_get_native_(ID_var) \
317 ((ID_var).native)
318/**
319 * Check whether @a ID_var variable is equal current thread
320 */
321# define MHD_thread_ID_is_current_thread_(ID_var) \
322 (MHD_thread_ID_is_valid_(ID_var) && \
323 MHD_thread_ID_native_is_current_thread_((ID_var).native))
324#else /* MHD_THREAD_ID_NATIVE_INVALID_ */
325/**
326 * Type with thread ID that can be set to invalid value
327 */
328typedef MHD_thread_ID_native_ MHD_thread_ID_;
329
330/**
331 * Set variable pointed by @a ID_ptr to invalid (unset) value
332 */
333# define MHD_thread_ID_set_invalid_(ID_ptr) \
334 ((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
335/**
336 * Set native ID in variable pointed by @a ID_ptr
337 * to @a native_val value
338 */
339# define MHD_thread_ID_set_native_(ID_ptr,native_val) \
340 ((*(ID_ptr)) = native_val)
341/**
342 * Check whether native ID value is set in @a ID_var variable
343 */
344# define MHD_thread_ID_is_valid_(ID_var) \
345 (MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != ID_var)
346/**
347 * Get native ID value from @a ID_var variable
348 */
349# define MHD_thread_ID_get_native_(ID_var) \
350 (ID_var)
351/**
352 * Check whether @a ID_var variable is equal current thread
353 */
354# define MHD_thread_ID_is_current_thread_(ID_var) \
355 MHD_thread_ID_native_is_current_thread_(ID_var)
356#endif /* MHD_THREAD_ID_NATIVE_INVALID_ */
357
358/**
359 * Set current thread ID in variable pointed by @a ID_ptr
360 */
361# define MHD_thread_ID_set_current_thread_(ID_ptr) \
362 MHD_thread_ID_set_native_(ID_ptr,MHD_thread_ID_native_current_())
363
364
365#if defined(MHD_USE_POSIX_THREADS)
366# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
367 ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
368# error \
369 MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined
370# elif ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
371 defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
372# error \
373 MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined
374# endif
375#endif /* MHD_USE_POSIX_THREADS */
376
377/* When staring a new thread, the kernel (and thread implementation) may
378 * pause the calling (initial) thread and start the new thread.
379 * If thread identifier is assigned to variable in the initial thread then
380 * the value of the identifier variable will be undefined in the new thread
381 * until the initial thread continue processing.
382 * However, it is also possible that the new thread created, but not executed
383 * for some time while the initial thread continue execution. In this case any
384 * variable assigned in the new thread will be undefined for some time until
385 * they really processed by the new thread.
386 * To avoid data races, a special structure MHD_thread_handle_ID_ is used.
387 * The "handle" is assigned by calling (initial) thread and should be always
388 * defined when checked in the initial thread.
389 * The "ID" is assigned by the new thread and should be always defined when
390 * checked inside the new thread.
391 */
105/* Depending on implementation, pthread_create() MAY set thread ID into 392/* Depending on implementation, pthread_create() MAY set thread ID into
106 * provided pointer and after it start thread OR start thread and after 393 * provided pointer and after it start thread OR start thread and after
107 * it set thread ID. In the latter case, to avoid data races, additional 394 * it set thread ID. In the latter case, to avoid data races, additional
@@ -109,95 +396,122 @@ typedef DWORD MHD_thread_ID_;
109 * is known for setting thread ID BEFORE starting thread macro 396 * is known for setting thread ID BEFORE starting thread macro
110 * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined 397 * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined
111 * to save some resources. */ 398 * to save some resources. */
399/* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */
400
112/* * handle - must be valid when other thread knows that particular thread 401/* * handle - must be valid when other thread knows that particular thread
113 is started. 402 is started.
114 * ID - must be valid when code is executed inside thread */ 403 * ID - must be valid when code is executed inside thread */
115#if defined(MHD_USE_POSIX_THREADS) 404#if defined(MHD_USE_POSIX_THREADS) && \
116# ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 405 defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \
406 defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
407 defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \
408 defined(MHD_thread_handle_get_native_ptr_)
117union _MHD_thread_handle_ID_ 409union _MHD_thread_handle_ID_
118{ 410{
119 MHD_thread_handle_ handle; /**< To be used in other threads */ 411 MHD_thread_handle_ handle; /**< To be used in other threads */
120 MHD_thread_ID_ ID; /**< To be used in thread itself */ 412 MHD_thread_ID_ ID; /**< To be used in the thread itself */
121}; 413};
122typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 414typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_;
123# else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 415# define MHD_THREAD_HANDLE_ID_IS_UNION 1
124struct _MHD_thread_handle_ID_ 416#else /* !MHD_USE_POSIX_THREADS
125{ 417 || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
126 MHD_thread_handle_ handle; /**< To be used in other threads */ 418 || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
127 MHD_thread_ID_ ID; /**< To be used in thread itself */ 419 || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
128}; 420 || !MHD_thread_handle_get_native_ptr_ */
129typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_;
130# endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */
131#elif defined(MHD_USE_W32_THREADS)
132struct _MHD_thread_handle_ID_ 421struct _MHD_thread_handle_ID_
133{ 422{
134 MHD_thread_handle_ handle; /**< To be used in other threads */ 423 MHD_thread_handle_ handle; /**< To be used in other threads */
135 MHD_thread_ID_ ID; /**< To be used in thread itself */ 424 MHD_thread_ID_ ID; /**< To be used in the thread itself */
136}; 425};
137typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_; 426typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_;
138#endif 427#endif /* !MHD_USE_POSIX_THREADS
428 || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
429 || !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
430 || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
431 || !MHD_thread_handle_get_native_ptr_ */
139 432
140#if defined(MHD_USE_POSIX_THREADS)
141/** 433/**
142 * Wait until specified thread is ended and free thread handle on success. 434 * Set MHD_thread_handle_ID_ to invalid value
143 * @param thread handle to watch
144 * @return nonzero on success, zero otherwise
145 */ 435 */
146#define MHD_join_thread_(thread) (! pthread_join ((thread), NULL)) 436#define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr) \
147#elif defined(MHD_USE_W32_THREADS) 437 (MHD_thread_handle_set_invalid_(&((hndl_id_ptr)->handle)), \
438 MHD_thread_ID_set_invalid_(&((hndl_id_ptr)->ID)))
439
148/** 440/**
149 * Wait until specified thread is ended and free thread handle on success. 441 * Check whether thread handle is valid.
150 * @param thread handle to watch 442 * To be used in threads other then the thread specified by @a hndl_id.
151 * @return nonzero on success, zero otherwise
152 */ 443 */
153#define MHD_join_thread_(thread) \ 444#define MHD_thread_handle_ID_is_valid_handle_(hndl_id) \
154 ( (WAIT_OBJECT_0 == WaitForSingleObject ( (thread), INFINITE)) ? \ 445 MHD_thread_handle_is_valid_((hndl_id).handle)
155 (CloseHandle ( (thread)), ! 0) : 0 )
156#endif
157 446
158#define MHD_join_thread_tid_(thread_handle_ID_ptr) \ 447/**
159 (MHD_join_thread_((thread_handle_ID_ptr)->handle)) 448 * Set native handle in variable pointed by @a hndl_id_ptr
449 * to @a native_val value
450 */
451#define MHD_thread_handle_ID_set_native_handle_(hndl_id_ptr,native_val) \
452 MHD_thread_handle_set_native_(&((hndl_id_ptr)->handle),native_val)
160 453
161#if defined(MHD_USE_POSIX_THREADS) 454#if defined(MHD_thread_handle_get_native_ptr_)
162/** 455/**
163 * Check whether provided thread ID matches current thread. 456 * Get pointer to native handle stored the variable pointed by @a hndl_id_ptr
164 * @param ID thread ID to match 457 * @note This macro could not available if direct manipulation of
165 * @return nonzero on match, zero otherwise 458 * the native handle is not possible
166 */ 459 */
167# define MHD_thread_ID_is_current_thread_(tid) \ 460# define MHD_thread_handle_ID_get_native_handle_ptr_(hndl_id_ptr) \
168 (pthread_equal ((tid).ID, pthread_self ())) 461 MHD_thread_handle_get_native_ptr_(&((hndl_id_ptr)->handle))
169#elif defined(MHD_USE_W32_THREADS) 462#endif /* MHD_thread_handle_get_native_ptr_ */
463
170/** 464/**
171 * Check whether provided thread ID matches current thread. 465 * Get native thread handle from MHD_thread_handle_ID_ variable.
172 * @param ID thread ID to match
173 * @return nonzero on match, zero otherwise
174 */ 466 */
175# define MHD_thread_ID_is_current_thread_(tid) \ 467#define MHD_thread_handle_ID_get_native_handle_(hndl_id) \
176 (GetCurrentThreadId () == (tid).ID) 468 MHD_thread_handle_get_native_((hndl_id).handle)
177#endif
178 469
179#if defined(MHD_USE_POSIX_THREADS)
180# ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
181/** 470/**
182 * Initialise thread ID. 471 * Check whether thread ID is valid.
183 * @param thread_handle_ID_ptr pointer to thread handle-ID 472 * To be used in the thread itself.
473 */
474#define MHD_thread_handle_ID_is_valid_ID_(hndl_id) \
475 MHD_thread_ID_is_valid_((hndl_id).ID)
476
477#if defined(MHD_THREAD_HANDLE_ID_IS_UNION)
478# if defined(MHD_USE_W32_THREADS)
479# error MHD_thread_handle_ID_ cannot be a union with W32 threads
480# endif /* MHD_USE_W32_THREADS */
481/**
482 * Set current thread ID in the variable pointed by @a hndl_id_ptr
184 */ 483 */
185#define MHD_thread_init_(thread_handle_ID_ptr) (void) 0 484# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) (void) 0
186# else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 485#else /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
187/** 486/**
188 * Initialise thread ID. 487 * Set current thread ID in the variable pointed by @a hndl_id_ptr
189 * @param thread_handle_ID_ptr pointer to thread handle-ID
190 */ 488 */
191#define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ 489# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) \
192 pthread_self ()) 490 MHD_thread_ID_set_current_thread_(&((hndl_id_ptr)->ID))
193# endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */ 491#endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
194#elif defined(MHD_USE_W32_THREADS) 492
493/**
494 * Check whether provided thread ID matches current thread.
495 * @param ID thread ID to match
496 * @return nonzero on match, zero otherwise
497 */
498#define MHD_thread_handle_ID_is_current_thread_(hndl_id) \
499 MHD_thread_ID_is_current_thread_((hndl_id).ID)
500
195/** 501/**
196 * Initialise thread ID. 502 * Wait until specified thread is ended and free thread handle on success.
197 * @param thread_handle_ID_ptr pointer to thread handle-ID 503 * @param hndl_id_ handle with ID to watch
504 * @return nonzero on success, zero otherwise
198 */ 505 */
199#define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \ 506#define MHD_thread_handle_ID_join_thread_(hndl_id) \
200 GetCurrentThreadId ()) 507 MHD_join_thread_(MHD_thread_handle_ID_get_native_handle_(hndl_id))
508
509#if defined(MHD_USE_POSIX_THREADS)
510# define MHD_THRD_RTRN_TYPE_ void*
511# define MHD_THRD_CALL_SPEC_
512#elif defined(MHD_USE_W32_THREADS)
513# define MHD_THRD_RTRN_TYPE_ unsigned
514# define MHD_THRD_CALL_SPEC_ __stdcall
201#endif 515#endif
202 516
203/** 517/**
@@ -215,14 +529,14 @@ typedef MHD_THRD_RTRN_TYPE_
215 * 529 *
216 * If thread is created, thread handle must be freed by MHD_join_thread_(). 530 * If thread is created, thread handle must be freed by MHD_join_thread_().
217 * 531 *
218 * @param thread handle to initialize 532 * @param handle_id handle to initialise
219 * @param stack_size size of stack for new thread, 0 for default 533 * @param stack_size size of stack for new thread, 0 for default
220 * @param start_routine main function of thread 534 * @param start_routine main function of thread
221 * @param arg argument for start_routine 535 * @param arg argument for start_routine
222 * @return non-zero on success; zero otherwise (with errno set) 536 * @return non-zero on success; zero otherwise (with errno set)
223 */ 537 */
224int 538int
225MHD_create_thread_ (MHD_thread_handle_ID_ *thread, 539MHD_create_thread_ (MHD_thread_handle_ID_ *handle_id,
226 size_t stack_size, 540 size_t stack_size,
227 MHD_THREAD_START_ROUTINE_ start_routine, 541 MHD_THREAD_START_ROUTINE_ start_routine,
228 void *arg); 542 void *arg);
@@ -233,7 +547,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
233/** 547/**
234 * Create a named thread and set the attributes according to our options. 548 * Create a named thread and set the attributes according to our options.
235 * 549 *
236 * @param thread handle to initialize 550 * @param handle_id handle to initialise
237 * @param thread_name name for new thread 551 * @param thread_name name for new thread
238 * @param stack_size size of stack for new thread, 0 for default 552 * @param stack_size size of stack for new thread, 0 for default
239 * @param start_routine main function of thread 553 * @param start_routine main function of thread
@@ -241,7 +555,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
241 * @return non-zero on success; zero otherwise 555 * @return non-zero on success; zero otherwise
242 */ 556 */
243int 557int
244MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread, 558MHD_create_named_thread_ (MHD_thread_handle_ID_ *handle_id,
245 const char *thread_name, 559 const char *thread_name,
246 size_t stack_size, 560 size_t stack_size,
247 MHD_THREAD_START_ROUTINE_ start_routine, 561 MHD_THREAD_START_ROUTINE_ start_routine,
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 8cd540b1..e96bf0d8 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -1941,7 +1941,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
1941 1941
1942#ifdef MHD_USE_THREADS 1942#ifdef MHD_USE_THREADS
1943 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \ 1943 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1944 MHD_thread_ID_is_current_thread_ (connection->tid) ); 1944 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
1945#endif /* MHD_USE_THREADS */ 1945#endif /* MHD_USE_THREADS */
1946 1946
1947 /* "Upgrade" responses accepted only if MHD_ALLOW_UPGRADE is enabled */ 1947 /* "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
index 9f68fd05..8bdafde7 100644
--- a/src/microhttpd/test_shutdown_select.c
+++ b/src/microhttpd/test_shutdown_select.c
@@ -322,7 +322,7 @@ main (int argc, char *const *argv)
322 */ 322 */
323 for (i = 0; i < 5 && result == 0; i++) 323 for (i = 0; i < 5 && result == 0; i++)
324 { 324 {
325 MHD_thread_handle_ sel_thrd; 325 MHD_thread_handle_native_ sel_thrd;
326 /* fprintf(stdout, "Creating, binding and listening socket...\n"); */ 326 /* fprintf(stdout, "Creating, binding and listening socket...\n"); */
327 MHD_socket listen_socket = start_socket_listen (AF_INET); 327 MHD_socket listen_socket = start_socket_listen (AF_INET);
328 if (MHD_INVALID_SOCKET == listen_socket) 328 if (MHD_INVALID_SOCKET == listen_socket)