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