|
|
@@ -2666,6 +2666,7 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
|
|
|
struct MHD_Connection *prev = NULL;
|
|
|
int ret;
|
|
|
const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
|
|
|
+ assert (NULL == daemon->worker_pool);
|
|
|
|
|
|
ret = MHD_NO;
|
|
|
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
@@ -5843,16 +5844,20 @@ MHD_start_daemon_va (unsigned int flags,
|
|
|
MHD_socket_close_chk_ (listen_fd);
|
|
|
goto free_and_fail;
|
|
|
}
|
|
|
- if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
|
|
|
- {
|
|
|
+ if (0 == daemon->worker_pool_size)
|
|
|
+ { /* Initialise connection mutex only if this daemon will handle
|
|
|
+ * any connections by itself. */
|
|
|
+ if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
|
|
|
+ {
|
|
|
#ifdef HAVE_MESSAGES
|
|
|
- MHD_DLOG (daemon,
|
|
|
- _("MHD failed to initialize IP connection limit mutex\n"));
|
|
|
+ MHD_DLOG (daemon,
|
|
|
+ _("MHD failed to initialize IP connection limit mutex\n"));
|
|
|
#endif
|
|
|
- MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
- if (MHD_INVALID_SOCKET != listen_fd)
|
|
|
- MHD_socket_close_chk_ (listen_fd);
|
|
|
- goto free_and_fail;
|
|
|
+ MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
+ if (MHD_INVALID_SOCKET != listen_fd)
|
|
|
+ MHD_socket_close_chk_ (listen_fd);
|
|
|
+ goto free_and_fail;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
#ifdef HTTPS_SUPPORT
|
|
|
@@ -5866,128 +5871,132 @@ MHD_start_daemon_va (unsigned int flags,
|
|
|
#endif
|
|
|
if (MHD_INVALID_SOCKET != listen_fd)
|
|
|
MHD_socket_close_chk_ (listen_fd);
|
|
|
- MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
+ if (0 == daemon->worker_pool_size)
|
|
|
+ MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
|
|
|
goto free_and_fail;
|
|
|
}
|
|
|
#endif /* HTTPS_SUPPORT */
|
|
|
- if ( ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
|
|
|
- (0 == daemon->worker_pool_size) ) &&
|
|
|
- (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
|
|
|
- (! MHD_create_named_thread_ (&daemon->pid,
|
|
|
- (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
|
|
|
- "MHD-listen" : "MHD-single",
|
|
|
- daemon->thread_stack_size,
|
|
|
- &MHD_polling_thread,
|
|
|
- daemon) ) )
|
|
|
+ if ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
|
|
|
+ (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
|
|
|
{
|
|
|
+ if (0 == daemon->worker_pool_size)
|
|
|
+ {
|
|
|
+ if (! MHD_create_named_thread_ (&daemon->pid,
|
|
|
+ (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
|
|
|
+ "MHD-listen" : "MHD-single",
|
|
|
+ daemon->thread_stack_size,
|
|
|
+ &MHD_polling_thread,
|
|
|
+ daemon) )
|
|
|
+ {
|
|
|
#ifdef HAVE_MESSAGES
|
|
|
- MHD_DLOG (daemon,
|
|
|
- _("Failed to create listen thread: %s\n"),
|
|
|
- MHD_strerror_ (errno));
|
|
|
+ MHD_DLOG (daemon,
|
|
|
+ _("Failed to create listen thread: %s\n"),
|
|
|
+ MHD_strerror_ (errno));
|
|
|
#endif
|
|
|
- MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
- MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
|
|
|
- if (MHD_INVALID_SOCKET != listen_fd)
|
|
|
- MHD_socket_close_chk_ (listen_fd);
|
|
|
- goto free_and_fail;
|
|
|
- }
|
|
|
- if ( (daemon->worker_pool_size > 0) &&
|
|
|
- (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
|
|
|
- {
|
|
|
- /* Coarse-grained count of connections per thread (note error
|
|
|
- * due to integer division). Also keep track of how many
|
|
|
- * connections are leftover after an equal split. */
|
|
|
- unsigned int conns_per_thread = daemon->connection_limit
|
|
|
- / daemon->worker_pool_size;
|
|
|
- unsigned int leftover_conns = daemon->connection_limit
|
|
|
- % daemon->worker_pool_size;
|
|
|
-
|
|
|
- i = 0; /* we need this in case fcntl or malloc fails */
|
|
|
-
|
|
|
- /* Allocate memory for pooled objects */
|
|
|
- daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
|
|
|
- * daemon->worker_pool_size);
|
|
|
- if (NULL == daemon->worker_pool)
|
|
|
- goto thread_failed;
|
|
|
-
|
|
|
- /* Start the workers in the pool */
|
|
|
- for (i = 0; i < daemon->worker_pool_size; ++i)
|
|
|
+ MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
+ MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
|
|
|
+ if (MHD_INVALID_SOCKET != listen_fd)
|
|
|
+ MHD_socket_close_chk_ (listen_fd);
|
|
|
+ goto free_and_fail;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else /* 0 < daemon->worker_pool_size */
|
|
|
{
|
|
|
- /* Create copy of the Daemon object for each worker */
|
|
|
- struct MHD_Daemon *d = &daemon->worker_pool[i];
|
|
|
-
|
|
|
- memcpy (d, daemon, sizeof (struct MHD_Daemon));
|
|
|
- /* Adjust pooling params for worker daemons; note that memcpy()
|
|
|
- has already copied MHD_USE_INTERNAL_POLLING_THREAD thread model into
|
|
|
- the worker threads. */
|
|
|
- d->master = daemon;
|
|
|
- d->worker_pool_size = 0;
|
|
|
- d->worker_pool = NULL;
|
|
|
-
|
|
|
- if (0 != (*pflags & MHD_USE_ITC))
|
|
|
+ /* Coarse-grained count of connections per thread (note error
|
|
|
+ * due to integer division). Also keep track of how many
|
|
|
+ * connections are leftover after an equal split. */
|
|
|
+ unsigned int conns_per_thread = daemon->connection_limit
|
|
|
+ / daemon->worker_pool_size;
|
|
|
+ unsigned int leftover_conns = daemon->connection_limit
|
|
|
+ % daemon->worker_pool_size;
|
|
|
+
|
|
|
+ i = 0; /* we need this in case fcntl or malloc fails */
|
|
|
+
|
|
|
+ /* Allocate memory for pooled objects */
|
|
|
+ daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
|
|
|
+ * daemon->worker_pool_size);
|
|
|
+ if (NULL == daemon->worker_pool)
|
|
|
+ goto thread_failed;
|
|
|
+
|
|
|
+ /* Start the workers in the pool */
|
|
|
+ for (i = 0; i < daemon->worker_pool_size; ++i)
|
|
|
{
|
|
|
- if (! MHD_itc_init_ (d->itc))
|
|
|
+ /* Create copy of the Daemon object for each worker */
|
|
|
+ struct MHD_Daemon *d = &daemon->worker_pool[i];
|
|
|
+
|
|
|
+ memcpy (d, daemon, sizeof (struct MHD_Daemon));
|
|
|
+ /* Adjust pooling params for worker daemons; note that memcpy()
|
|
|
+ has already copied MHD_USE_INTERNAL_POLLING_THREAD thread model into
|
|
|
+ the worker threads. */
|
|
|
+ d->master = daemon;
|
|
|
+ d->worker_pool_size = 0;
|
|
|
+ d->worker_pool = NULL;
|
|
|
+
|
|
|
+ if (0 != (*pflags & MHD_USE_ITC))
|
|
|
{
|
|
|
+ if (! MHD_itc_init_ (d->itc))
|
|
|
+ {
|
|
|
#ifdef HAVE_MESSAGES
|
|
|
- MHD_DLOG (daemon,
|
|
|
- _("Failed to create worker inter-thread communication channel: %s\n"),
|
|
|
- MHD_itc_last_strerror_() );
|
|
|
+ MHD_DLOG (daemon,
|
|
|
+ _("Failed to create worker inter-thread communication channel: %s\n"),
|
|
|
+ MHD_itc_last_strerror_() );
|
|
|
#endif
|
|
|
- goto thread_failed;
|
|
|
- }
|
|
|
- if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
|
|
|
- (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
|
|
|
- NULL)) )
|
|
|
- {
|
|
|
+ goto thread_failed;
|
|
|
+ }
|
|
|
+ if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
|
|
|
+ (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
|
|
|
+ NULL)) )
|
|
|
+ {
|
|
|
#ifdef HAVE_MESSAGES
|
|
|
- MHD_DLOG (daemon,
|
|
|
- _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
|
|
|
+ MHD_DLOG (daemon,
|
|
|
+ _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
|
|
|
#endif
|
|
|
- MHD_itc_destroy_chk_ (d->itc);
|
|
|
- goto thread_failed;
|
|
|
+ MHD_itc_destroy_chk_ (d->itc);
|
|
|
+ goto thread_failed;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
- MHD_itc_set_invalid_ (d->itc);
|
|
|
-
|
|
|
- /* Divide available connections evenly amongst the threads.
|
|
|
- * Thread indexes in [0, leftover_conns) each get one of the
|
|
|
- * leftover connections. */
|
|
|
- d->connection_limit = conns_per_thread;
|
|
|
- if (i < leftover_conns)
|
|
|
- ++d->connection_limit;
|
|
|
+ else
|
|
|
+ MHD_itc_set_invalid_ (d->itc);
|
|
|
+
|
|
|
+ /* Divide available connections evenly amongst the threads.
|
|
|
+ * Thread indexes in [0, leftover_conns) each get one of the
|
|
|
+ * leftover connections. */
|
|
|
+ d->connection_limit = conns_per_thread;
|
|
|
+ if (i < leftover_conns)
|
|
|
+ ++d->connection_limit;
|
|
|
#ifdef EPOLL_SUPPORT
|
|
|
- if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
|
|
|
- (MHD_YES != setup_epoll_to_listen (d)) )
|
|
|
- goto thread_failed;
|
|
|
+ if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
|
|
|
+ (MHD_YES != setup_epoll_to_listen (d)) )
|
|
|
+ goto thread_failed;
|
|
|
#endif
|
|
|
- /* Must init cleanup connection mutex for each worker */
|
|
|
- if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
|
|
|
- {
|
|
|
+ /* Must init cleanup connection mutex for each worker */
|
|
|
+ if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
|
|
|
+ {
|
|
|
#ifdef HAVE_MESSAGES
|
|
|
- MHD_DLOG (daemon,
|
|
|
- _("MHD failed to initialize cleanup connection mutex\n"));
|
|
|
+ MHD_DLOG (daemon,
|
|
|
+ _("MHD failed to initialize cleanup connection mutex\n"));
|
|
|
#endif
|
|
|
- goto thread_failed;
|
|
|
- }
|
|
|
+ goto thread_failed;
|
|
|
+ }
|
|
|
|
|
|
- /* Spawn the worker thread */
|
|
|
- if (! MHD_create_named_thread_ (&d->pid,
|
|
|
- "MHD-worker",
|
|
|
- daemon->thread_stack_size,
|
|
|
- &MHD_polling_thread,
|
|
|
- d))
|
|
|
- {
|
|
|
+ /* Spawn the worker thread */
|
|
|
+ if (! MHD_create_named_thread_ (&d->pid,
|
|
|
+ "MHD-worker",
|
|
|
+ daemon->thread_stack_size,
|
|
|
+ &MHD_polling_thread,
|
|
|
+ d))
|
|
|
+ {
|
|
|
#ifdef HAVE_MESSAGES
|
|
|
- MHD_DLOG (daemon,
|
|
|
- _("Failed to create pool thread: %s\n"),
|
|
|
- MHD_strerror_ (errno));
|
|
|
+ MHD_DLOG (daemon,
|
|
|
+ _("Failed to create pool thread: %s\n"),
|
|
|
+ MHD_strerror_ (errno));
|
|
|
#endif
|
|
|
- /* Free memory for this worker; cleanup below handles
|
|
|
- * all previously-created workers. */
|
|
|
- MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
|
|
|
- goto thread_failed;
|
|
|
+ /* Free memory for this worker; cleanup below handles
|
|
|
+ * all previously-created workers. */
|
|
|
+ MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
|
|
|
+ goto thread_failed;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -6008,7 +6017,6 @@ thread_failed:
|
|
|
{
|
|
|
if (MHD_INVALID_SOCKET != listen_fd)
|
|
|
MHD_socket_close_chk_ (listen_fd);
|
|
|
- MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
|
|
|
if (NULL != daemon->worker_pool)
|
|
|
free (daemon->worker_pool);
|
|
|
@@ -6081,6 +6089,7 @@ close_all_connections (struct MHD_Daemon *daemon)
|
|
|
struct MHD_UpgradeResponseHandle *urhn;
|
|
|
const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
|
|
|
|
|
|
+ assert (NULL == daemon->worker_pool);
|
|
|
/* give upgraded HTTPS connections a chance to finish */
|
|
|
/* 'daemon->urh_head' is not used in thread-per-connection mode. */
|
|
|
for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
|
|
|
@@ -6223,7 +6232,8 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
|
|
|
if (NULL == daemon)
|
|
|
return;
|
|
|
|
|
|
- if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
|
|
|
+ if ( (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options)) &&
|
|
|
+ (NULL == daemon->worker_pool) )
|
|
|
resume_suspended_connections (daemon);
|
|
|
|
|
|
daemon->shutdown = true;
|
|
|
@@ -6341,7 +6351,8 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
|
|
|
MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
|
|
|
#endif
|
|
|
MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
|
|
|
- MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
+ if (NULL != daemon->worker_pool)
|
|
|
+ MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
|
|
|
|
|
|
free (daemon);
|
|
|
}
|