summaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c181
1 files changed, 88 insertions, 93 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index e176fae4..210b929f 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -90,6 +90,17 @@
*/
#define DEBUG_CONNECT MHD_NO
+/* Forward declarations. */
+/**
+ * Close all connections for the daemon.
+ * Must only be called when MHD_Daemon::shutdown was set to MHD_YES.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
+ *
+ * @param daemon daemon to close down
+ */
+static void
+close_all_connections (struct MHD_Daemon *daemon);
/**
* Default implementation of the panic function,
@@ -5510,105 +5521,101 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
#endif
if (0 != (MHD_USE_SUSPEND_RESUME & daemon->options))
resume_suspended_connections (daemon);
+
daemon->shutdown = MHD_YES;
fd = daemon->socket_fd;
daemon->socket_fd = MHD_INVALID_SOCKET;
- /* Prepare workers for shutdown */
- if (NULL != daemon->worker_pool)
- {
- /* #MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */
- for (i = 0; i < daemon->worker_pool_size; ++i)
- {
- daemon->worker_pool[i].shutdown = MHD_YES;
- daemon->worker_pool[i].socket_fd = MHD_INVALID_SOCKET;
-#ifdef EPOLL_SUPPORT
- if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
- (-1 != daemon->worker_pool[i].epoll_fd) &&
- (MHD_INVALID_SOCKET == fd) )
- epoll_shutdown (&daemon->worker_pool[i]);
-#endif
- }
- }
- if (MHD_ITC_IS_VALID_(daemon->itc))
+
+ if ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ||
+ (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
{
- if (! MHD_itc_activate_ (daemon->itc, "e"))
- MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
- }
+ /* Separate thread(s) is used for select()/poll()/etc. */
+ if (NULL != daemon->worker_pool)
+ {
+ /* Pool of workers is used. */
+ /* Initiate shutdown process in wokers. */
+ for (i = 0; i < daemon->worker_pool_size; ++i)
+ {
+ daemon->worker_pool[i].shutdown = MHD_YES;
+ daemon->worker_pool[i].socket_fd = MHD_INVALID_SOCKET;
+ if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
+ {
+ if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
+ MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
+ }
#ifdef HAVE_LISTEN_SHUTDOWN
- else
- {
- /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
- if ( (MHD_INVALID_SOCKET != fd) &&
- (0 == (daemon->options & MHD_USE_ITC)) )
- (void) shutdown (fd,
- SHUT_RDWR);
- }
-#endif
-#ifdef EPOLL_SUPPORT
- if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
- (-1 != daemon->epoll_fd) &&
- (MHD_INVALID_SOCKET == fd) )
- epoll_shutdown (daemon);
-#endif
-
-#if DEBUG_CLOSE
-#ifdef HAVE_MESSAGES
- MHD_DLOG (daemon,
- _("MHD listen socket shutdown\n"));
-#endif
+ else if (MHD_INVALID_SOCKET != fd)
+ {
+ /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
+ /* No problem if shutdown will be called several times for the same socket. */
+ (void) shutdown (fd, SHUT_RDWR);
+ }
#endif
-
-
- /* Signal workers to stop and clean them up */
- if (NULL != daemon->worker_pool)
- {
- /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */
- for (i = 0; i < daemon->worker_pool_size; ++i)
- {
- if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
- {
- if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
- MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
- }
- if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
- MHD_PANIC (_("Failed to join a thread\n"));
- MHD_mutex_destroy_chk_ (&daemon->worker_pool[i].cleanup_connection_mutex);
+ }
+ /* Start harvesting. */
+ for (i = 0; i < daemon->worker_pool_size; ++i)
+ {
+ if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
+ MHD_PANIC (_("Failed to join a thread\n"));
#ifdef EPOLL_SUPPORT
- if (-1 != daemon->worker_pool[i].epoll_fd)
- MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
+ if (-1 != daemon->worker_pool[i].epoll_fd)
+ MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
#if HTTPS_SUPPORT
- if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
- MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
+ if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
+ MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
#endif
#endif
- /* Individual ITCs are always used */
- if (1)
- {
if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc) )
- {
- MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
- }
- }
- }
- free (daemon->worker_pool);
+ MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
+ MHD_mutex_destroy_chk_ (&daemon->worker_pool[i].cleanup_connection_mutex);
+ }
+ free (daemon->worker_pool);
+ }
+ else
+ {
+ /* Single internal thread is used for select()/poll()/etc. */
+ if (MHD_ITC_IS_VALID_(daemon->itc))
+ {
+ if (! MHD_itc_activate_ (daemon->itc, "e"))
+ MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
+ }
+#ifdef HAVE_LISTEN_SHUTDOWN
+ else
+ {
+ /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
+ if (MHD_INVALID_SOCKET != fd)
+ (void) shutdown (fd, SHUT_RDWR);
+ }
+#endif
+ if (! MHD_join_thread_ (daemon->pid))
+ {
+ MHD_PANIC (_("Failed to join a thread\n"));
+ }
+ }
}
else
{
- /* clean up master threads */
- if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
- ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
- (0 == daemon->worker_pool_size) ) )
- {
- if (! MHD_join_thread_ (daemon->pid))
- {
- MHD_PANIC (_("Failed to join a thread\n"));
- }
- }
+ /* Internal threads are not used for select()/poll()/etc. */
+ close_all_connections (daemon);
}
- close_all_connections (daemon);
+
if (MHD_INVALID_SOCKET != fd)
MHD_socket_close_chk_ (fd);
+ if (MHD_ITC_IS_VALID_ (daemon->itc))
+ MHD_itc_destroy_chk_ (daemon->itc);
+
+#ifdef EPOLL_SUPPORT
+ if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
+ (-1 != daemon->epoll_fd) )
+ MHD_socket_close_chk_ (daemon->epoll_fd);
+#if HTTPS_SUPPORT
+ if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
+ (-1 != daemon->epoll_upgrade_fd) )
+ MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
+#endif
+#endif
+
/* TLS clean up */
#if HTTPS_SUPPORT
if (MHD_YES == daemon->have_dhparams)
@@ -5623,16 +5630,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
gnutls_certificate_free_credentials (daemon->x509_cred);
}
#endif
-#ifdef EPOLL_SUPPORT
- if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
- (-1 != daemon->epoll_fd) )
- MHD_socket_close_chk_ (daemon->epoll_fd);
-#if HTTPS_SUPPORT
- if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
- (-1 != daemon->epoll_upgrade_fd) )
- MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
-#endif
-#endif
#ifdef DAUTH_SUPPORT
free (daemon->nnc);
@@ -5641,8 +5638,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
- if (MHD_ITC_IS_VALID_(daemon->itc))
- MHD_itc_destroy_chk_ (daemon->itc);
free (daemon);
}