GNU libmicrohttpd  0.9.72
daemon_close_all_connections.c
Go to the documentation of this file.
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 
25 #include "internal.h"
26 #include "connection_cleanup.h"
27 #include "connection_close.h"
30 #include "request_resume.h"
31 #include "upgrade_process.h"
32 
33 
42 static void
44 {
45  struct MHD_Daemon *daemon = pos->daemon;
46 
47  if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
48  {
50  return; /* must let thread to do the rest */
51  }
54 
56 
57  mhd_assert (! pos->suspended);
58  mhd_assert (! pos->resuming);
59  if (pos->connection_timeout ==
62  daemon->normal_timeout_tail,
63  pos);
64  else
66  daemon->manual_timeout_tail,
67  pos);
69  daemon->connections_tail,
70  pos);
71  DLL_insert (daemon->cleanup_head,
72  daemon->cleanup_tail,
73  pos);
74 
76 }
77 
78 
88 void
90 {
91  struct MHD_Connection *pos;
92  const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION ==
94 #ifdef UPGRADE_SUPPORT
95  const bool upg_allowed = (! daemon->disallow_upgrade);
96 #endif /* UPGRADE_SUPPORT */
97 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
98  struct MHD_UpgradeResponseHandle *urh;
99  struct MHD_UpgradeResponseHandle *urhn;
100  const bool used_tls = (NULL != daemon->tls_api);
101 
102  mhd_assert (NULL == daemon->worker_pool);
103  mhd_assert (daemon->shutdown);
104  /* give upgraded HTTPS connections a chance to finish */
105  /* 'daemon->urh_head' is not used in thread-per-connection mode. */
106  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
107  {
108  urhn = urh->prev;
109  /* call generic forwarding function for passing data
110  with chance to detect that application is done. */
111  MHD_upgrade_response_handle_process_ (urh);
112  MHD_connection_finish_forward_ (urh->connection);
113  urh->clean_ready = true;
114  /* Resuming will move connection to cleanup list. */
115  MHD_request_resume (&urh->connection->request);
116  }
117 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
118 
119  /* Give suspended connections a chance to resume to avoid
120  running into the check for there not being any suspended
121  connections left in case of a tight race with a recently
122  resumed connection. */
123  if (! daemon->disallow_suspend_resume)
124  {
125  daemon->resuming = true; /* Force check for pending resume. */
127  }
128  /* first, make sure all threads are aware of shutdown; need to
129  traverse DLLs in peace... */
131 #ifdef UPGRADE_SUPPORT
132  if (upg_allowed)
133  {
134  struct MHD_Connection *susp;
135 
137  while (NULL != susp)
138  {
139  if (NULL == susp->request.urh) /* "Upgraded" connection? */
140  MHD_PANIC (_ (
141  "MHD_stop_daemon() called while we have suspended connections.\n"));
142 #ifdef HTTPS_SUPPORT
143  else if (used_tls &&
144  used_thr_p_c &&
145  (! susp->request.urh->clean_ready) )
146  shutdown (susp->request.urh->app.socket,
147  SHUT_RDWR); /* Wake thread by shutdown of app socket. */
148 #endif /* HTTPS_SUPPORT */
149  else
150  {
151 #ifdef HAVE_MESSAGES
152  if (! susp->request.urh->was_closed)
153  MHD_DLOG (daemon,
154  MHD_SC_SHUTDOWN_WITH_OPEN_UPGRADED_CONNECTION,
155  _ (
156  "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
157 #endif
158  susp->request.urh->was_closed = true;
159  /* If thread-per-connection is used, connection's thread
160  * may still processing "upgrade" (exiting). */
161  if (! used_thr_p_c)
163  /* Do not use MHD_resume_connection() as mutex is
164  * already locked. */
165  susp->resuming = true;
166  daemon->resuming = true;
167  }
168  susp = susp->prev;
169  }
170  }
171  else /* This 'else' is combined with next 'if' */
172 #endif /* UPGRADE_SUPPORT */
174  MHD_PANIC (_ (
175  "MHD_stop_daemon() called while we have suspended connections.\n"));
176  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
177  {
178  shutdown (pos->socket_fd,
179  SHUT_RDWR);
180 #if MHD_WINSOCK_SOCKETS
181  if ( (used_thr_p_c) &&
182  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
183  (! MHD_itc_activate_ (daemon->itc,
184  "e")) )
185  MHD_PANIC (_ (
186  "Failed to signal shutdown via inter-thread communication channel.\n"));
187 #endif
188  }
189 
190  /* now, collect per-connection threads */
191  if (used_thr_p_c)
192  {
193  pos = daemon->connections_tail;
194  while (NULL != pos)
195  {
196  if (! pos->thread_joined)
197  {
199  if (! MHD_join_thread_ (pos->pid.handle))
200  MHD_PANIC (_ ("Failed to join a thread.\n"));
202  pos->thread_joined = true;
203  /* The thread may have concurrently modified the DLL,
204  need to restart from the beginning */
205  pos = daemon->connections_tail;
206  continue;
207  }
208  pos = pos->prev;
209  }
210  }
212 
213 #ifdef UPGRADE_SUPPORT
214  /* Finished threads with "upgraded" connections need to be moved
215  * to cleanup list by resume_suspended_connections(). */
216  /* "Upgraded" connections that were not closed explicitly by
217  * application should be moved to cleanup list too. */
218  if (upg_allowed)
219  {
220  daemon->resuming = true; /* Force check for pending resume. */
222  }
223 #endif /* UPGRADE_SUPPORT */
224 
225  /* now that we're alone, move everyone to cleanup */
226  while (NULL != (pos = daemon->connections_tail))
227  {
228  if ( (used_thr_p_c) &&
229  (! pos->thread_joined) )
230  MHD_PANIC (_ ("Failed to join a thread.\n"));
231  close_connection (pos);
232  }
234 }
235 
236 
237 /* end of daemon_close_all_connections.c */
void MHD_connection_cleanup_(struct MHD_Daemon *daemon)
functions to cleanup completed connection
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
functions to close connection
complete upgrade socket forwarding operation in TLS mode
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
static void close_connection(struct MHD_Connection *pos)
void MHD_daemon_close_all_connections_(struct MHD_Daemon *daemon)
function to close all connections open at a daemon
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
Definition: microhttpd.h:1861
#define DLL_insert(head, tail, element)
Definition: internal.h:1743
#define MHD_PANIC(msg)
Definition: internal.h:69
#define XDLL_remove(head, tail, element)
Definition: internal.h:1806
#define DLL_remove(head, tail, element)
Definition: internal.h:1763
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:180
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
#define NULL
Definition: reason_phrase.c:30
#define _(String)
Definition: mhd_options.h:42
internal shared structures
void MHD_request_resume(struct MHD_Request *request)
bool MHD_resume_suspended_connections_(struct MHD_Daemon *daemon)
implementation of MHD_request_resume()
MHD_socket socket_fd
Definition: internal.h:752
bool suspended
Definition: internal.h:764
struct MHD_Request request
Definition: internal.h:717
time_t connection_timeout
Definition: internal.h:745
struct MHD_Connection * prev
Definition: internal.h:656
MHD_thread_handle_ID_ pid
Definition: internal.h:723
struct MHD_Daemon * daemon
Definition: internal.h:675
bool thread_joined
Definition: internal.h:779
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
struct MHD_Connection * connections_head
Definition: internal.h:1155
struct MHD_itc_ itc
Definition: internal.h:1410
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
bool disallow_upgrade
Definition: internal.h:1474
volatile bool shutdown
Definition: internal.h:1526
bool disallow_suspend_resume
Definition: internal.h:1468
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
bool resuming
Definition: internal.h:1510
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
time_t connection_default_timeout
Definition: internal.h:1371
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
struct MHD_Connection * cleanup_head
Definition: internal.h:1177
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1417
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
struct MHD_Connection * connections_tail
Definition: internal.h:1160
function to process upgrade activity (over TLS)