aboutsummaryrefslogtreecommitdiff
path: root/src/lib/daemon_quiesce.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/daemon_quiesce.c')
-rw-r--r--src/lib/daemon_quiesce.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/lib/daemon_quiesce.c b/src/lib/daemon_quiesce.c
new file mode 100644
index 00000000..31104a7d
--- /dev/null
+++ b/src/lib/daemon_quiesce.c
@@ -0,0 +1,127 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
20/**
21 * @file lib/daemon.c
22 * @brief main functions to quiesce a daemon
23 * @author Christian Grothoff
24 */
25#include "internal.h"
26
27
28/**
29 * Stop accepting connections from the listening socket. Allows
30 * clients to continue processing, but stops accepting new
31 * connections. Note that the caller is responsible for closing the
32 * returned socket; however, if MHD is run using threads (anything but
33 * external select mode), it must not be closed until AFTER
34 * #MHD_stop_daemon has been called (as it is theoretically possible
35 * that an existing thread is still using it).
36 *
37 * Note that some thread modes require the caller to have passed
38 * #MHD_USE_ITC when using this API. If this daemon is
39 * in one of those modes and this option was not given to
40 * #MHD_start_daemon, this function will return #MHD_INVALID_SOCKET.
41 *
42 * @param daemon daemon to stop accepting new connections for
43 * @return old listen socket on success, #MHD_INVALID_SOCKET if
44 * the daemon was already not listening anymore, or
45 * was never started
46 * @ingroup specialized
47 */
48MHD_socket
49MHD_daemon_quiesce (struct MHD_Daemon *daemon)
50{
51 MHD_socket listen_socket;
52
53 if (MHD_INVALID_SOCKET == (listen_socket = daemon->listen_socket))
54 return MHD_INVALID_SOCKET;
55 if ( (daemon->disable_itc) &&
56 (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_model) )
57 {
58#ifdef HAVE_MESSAGES
59 MHD_DLOG (daemon,
60 MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC,
61 "Using MHD_quiesce_daemon in this mode requires ITC\n");
62#endif
63 return MHD_INVALID_SOCKET;
64 }
65
66 if (NULL != daemon->worker_pool)
67 {
68 unsigned int i;
69
70 for (i = 0; i < daemon->threading_model; i++)
71 {
72 struct MHD_Daemon *worker = &daemon->worker_pool[i];
73
74 worker->was_quiesced = true;
75#ifdef EPOLL_SUPPORT
76 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
77 (-1 != worker->epoll_fd) &&
78 (worker->listen_socket_in_epoll) )
79 {
80 if (0 != epoll_ctl (worker->epoll_fd,
81 EPOLL_CTL_DEL,
82 listen_socket,
83 NULL))
84 MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
85 worker->listen_socket_in_epoll = false;
86 }
87 else
88#endif
89 if (MHD_ITC_IS_VALID_(worker->itc))
90 {
91 if (! MHD_itc_activate_ (worker->itc,
92 "q"))
93 MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
94 }
95 }
96 daemon->was_quiesced = true;
97#ifdef EPOLL_SUPPORT
98 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
99 (-1 != daemon->epoll_fd) &&
100 (daemon->listen_socket_in_epoll) )
101 {
102 if (0 != epoll_ctl (daemon->epoll_fd,
103 EPOLL_CTL_DEL,
104 listen_socket,
105 NULL))
106 MHD_PANIC ("Failed to remove listen FD from epoll set\n");
107 daemon->listen_socket_in_epoll = false;
108 }
109#endif
110 }
111
112 if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
113 (! MHD_itc_activate_ (daemon->itc,
114 "q")) )
115 MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
116
117 /* FIXME: we might want some bi-directional communication here
118 (in both the thread-pool and single-thread case!)
119 to be sure that the threads have stopped using the listen
120 socket, otherwise there is still the possibility of a race
121 between a thread accept()ing and the caller closing and
122 re-binding the socket. */
123
124 return listen_socket;
125}
126
127