GNU libmicrohttpd  0.9.72
daemon_destroy.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 "request_resume.h"
28 
29 
35 static void
36 stop_workers (struct MHD_Daemon *daemon)
37 {
38  MHD_socket fd;
39  unsigned int i;
40 
41  mhd_assert (1 < daemon->worker_pool_size);
42  mhd_assert (1 < daemon->threading_mode);
43  if (daemon->was_quiesced)
44  fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
45  else
46  fd = daemon->listen_socket;
47  /* Let workers shutdown in parallel. */
48  for (i = 0; i < daemon->worker_pool_size; i++)
49  {
50  daemon->worker_pool[i].shutdown = true;
51  if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
52  {
53  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
54  "e"))
55  MHD_PANIC (_ (
56  "Failed to signal shutdown via inter-thread communication channel.\n"));
57  }
58  else
59  {
60  /* Better hope shutdown() works... */
62  }
63  }
64 #ifdef HAVE_LISTEN_SHUTDOWN
65  if (MHD_INVALID_SOCKET != fd)
66  {
67  (void) shutdown (fd,
68  SHUT_RDWR);
69  }
70 #endif /* HAVE_LISTEN_SHUTDOWN */
71  for (i = 0; i < daemon->worker_pool_size; ++i)
72  {
73  MHD_daemon_destroy (&daemon->worker_pool[i]);
74  }
75  free (daemon->worker_pool);
76  daemon->worker_pool = NULL;
77  /* FIXME: does this still hold? */
79 #ifdef EPOLL_SUPPORT
80  mhd_assert (-1 == daemon->epoll_fd);
81 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
82  mhd_assert (-1 == daemon->epoll_upgrade_fd);
83 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
84 #endif /* EPOLL_SUPPORT */
85 }
86 
87 
94 void
96 {
97  MHD_socket fd;
98 
99  daemon->shutdown = true;
100  if (daemon->was_quiesced)
101  fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
102  else
103  fd = daemon->listen_socket;
104 
105  /* FIXME: convert from here to microhttpd2-style API! */
106 
107  if (NULL != daemon->worker_pool)
108  { /* Master daemon with worker pool. */
109  stop_workers (daemon);
110  }
111  else
112  {
113  mhd_assert (0 == daemon->worker_pool_size);
114  /* Worker daemon or single-thread daemon. */
115  if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode)
116  {
117  /* Worker daemon or single daemon with internal thread(s). */
118  /* Separate thread(s) is used for polling sockets. */
119  if (MHD_ITC_IS_VALID_ (daemon->itc))
120  {
121  if (! MHD_itc_activate_ (daemon->itc,
122  "e"))
123  MHD_PANIC (_ (
124  "Failed to signal shutdown via inter-thread communication channel.\n"));
125  }
126  else
127  {
128 #ifdef HAVE_LISTEN_SHUTDOWN
129  if (MHD_INVALID_SOCKET != fd)
130  {
131  if (NULL == daemon->master)
132  (void) shutdown (fd,
133  SHUT_RDWR);
134  }
135  else
136 #endif /* HAVE_LISTEN_SHUTDOWN */
137  mhd_assert (false); /* Should never happen */
138  }
139 
140  if (! MHD_join_thread_ (daemon->pid.handle))
141  {
142  MHD_PANIC (_ ("Failed to join a thread.\n"));
143  }
144  /* close_all_connections() was called in daemon thread. */
145  }
146  else
147  {
148  /* No internal threads are used for polling sockets
149  (external event loop) */
151  }
152  if (MHD_ITC_IS_VALID_ (daemon->itc))
153  MHD_itc_destroy_chk_ (daemon->itc);
154 
155 #ifdef EPOLL_SUPPORT
156  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
157  (-1 != daemon->epoll_fd) )
158  MHD_socket_close_chk_ (daemon->epoll_fd);
159 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
160  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
161  (-1 != daemon->epoll_upgrade_fd) )
162  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
163 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
164 #endif /* EPOLL_SUPPORT */
165 
167  }
168 
169  if (NULL != daemon->master)
170  return;
171  /* Cleanup that should be done only one time in master/single daemon.
172  * Do not perform this cleanup in worker daemons. */
173 
174  if (MHD_INVALID_SOCKET != fd)
176 
177  /* TLS clean up */
178 #ifdef HTTPS_SUPPORT
179  if (NULL != daemon->tls_api)
180  {
181 #if FIXME_TLS_API
182  if (daemon->have_dhparams)
183  {
184  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
185  daemon->have_dhparams = false;
186  }
187  gnutls_priority_deinit (daemon->priority_cache);
188  if (daemon->x509_cred)
189  gnutls_certificate_free_credentials (daemon->x509_cred);
190 #endif
191  }
192 #endif /* HTTPS_SUPPORT */
193 
194 #ifdef DAUTH_SUPPORT
195  free (daemon->nnc);
196  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
197 #endif
199  free (daemon);
200 }
201 
202 
203 /* end of daemon_destroy.c */
void MHD_daemon_close_all_connections_(struct MHD_Daemon *daemon)
function to close all connections open at a daemon
static void stop_workers(struct MHD_Daemon *daemon)
void MHD_daemon_destroy(struct MHD_Daemon *daemon)
#define MHD_PANIC(msg)
Definition: internal.h:69
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define MHD_ITC_IS_INVALID_(itc)
Definition: mhd_itc.h:367
#define MHD_itc_destroy_chk_(itc)
Definition: mhd_itc.h:353
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:121
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:248
#define NULL
Definition: reason_phrase.c:30
#define _(String)
Definition: mhd_options.h:42
internal shared structures
int MHD_socket
Definition: microhttpd.h:196
int fd
Definition: microhttpd.h:3195
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:197
implementation of MHD_request_resume()
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1259
bool was_quiesced
Definition: internal.h:1505
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
unsigned int worker_pool_size
Definition: internal.h:1366
struct MHD_itc_ itc
Definition: internal.h:1410
enum MHD_EventLoopSyscall event_loop_syscall
Definition: internal.h:1436
volatile bool shutdown
Definition: internal.h:1526
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
MHD_socket listen_socket
Definition: internal.h:1377
struct MHD_Daemon * master
Definition: internal.h:1068
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1417