Skip to content

Instantly share code, notes, and snippets.

@scottjg
Last active December 16, 2015 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottjg/5458005 to your computer and use it in GitHub Desktop.
Save scottjg/5458005 to your computer and use it in GitHub Desktop.
diff --git a/configure.ac b/configure.ac
index ad3b102..071d985 100644
--- a/configure.ac
+++ b/configure.ac
@@ -132,7 +132,7 @@ netbsd*)
;;
*linux*)
AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux kernel])
- AC_DEFINE_UNQUOTED(HAVE_LISTEN_SHUTDOWN,1,[can use shutdown on listen sockets])
+ #AC_DEFINE_UNQUOTED(HAVE_LISTEN_SHUTDOWN,1,[can use shutdown on listen sockets])
AM_CONDITIONAL(HAVE_GNU_LD, true)
AM_CONDITIONAL(HAVE_W32, false)
;;
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index bdd9f87..c40dba5 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -1352,7 +1352,7 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
const fd_set *write_fd_set,
const fd_set *except_fd_set)
{
- int ds;
+ int ds, tmp;
struct MHD_Connection *pos;
struct MHD_Connection *next;
@@ -1360,6 +1360,10 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
if ( (-1 != (ds = daemon->socket_fd)) &&
(FD_ISSET (ds, read_fd_set)) )
MHD_accept_connection (daemon);
+ /* drain signaling pipe to avoid spinning select */
+ if ( (-1 != daemon->wpipe[0]) &&
+ (FD_ISSET(daemon->wpipe[0], read_fd_set)) )
+ read(daemon->wpipe[0], &tmp, sizeof(tmp));
if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
{
/* do not have a thread per connection, process all connections now */
@@ -2692,6 +2696,51 @@ close_all_connections (struct MHD_Daemon *daemon)
MHD_cleanup_connections (daemon);
}
+/**
+ * Shutdown http daemon listening sockets.
+ *
+ * Allows clients to continue processing, but stops accepting connections
+ *
+ * @param daemon daemon to stop
+ */
+void
+MHD_quiesce_daemon (struct MHD_Daemon *daemon)
+{
+ int i, fd;
+
+ if (NULL == daemon)
+ return;
+
+ /*
+ * replace existing listening sockets with dummy sockets so event loops
+ * can continue operating normally. MHD_stop_daemon () will terminate the
+ * clients and finish cleanup.
+ */
+ fd = daemon->socket_fd;
+ daemon->socket_fd = create_socket (PF_INET, SOCK_STREAM, 0);
+ LISTEN (daemon->socket_fd, 20);
+ 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].socket_fd = daemon->socket_fd;
+ }
+ }
+
+ if (-1 != daemon->wpipe[1])
+ {
+ if (1 != WRITE (daemon->wpipe[1], "e", 1))
+ MHD_PANIC ("failed to signal shutdownn via pipe");
+ }
+#ifdef HAVE_LISTEN_SHUTDOWN
+ else
+ {
+ #error "HAVE_LISTEN_SHUTDOWN breaks rolling deploys, since shutdown() means forks can't call accept() on the same socket
+ }
+#endif
+}
+
/**
* Shutdown an http daemon
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 4da2619..672223d 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -1111,6 +1111,17 @@ MHD_stop_daemon (struct MHD_Daemon *daemon);
/**
+ * Shutdown http daemon listening sockets.
+ *
+ * Allows clients to continue processing, but stops accepting connections
+ *
+ * @param daemon daemon to stop
+ */
+void
+MHD_quiesce_daemon (struct MHD_Daemon *daemon);
+
+
+/**
* Add another client connection to the set of connections
* managed by MHD. This API is usually not needed (since
* MHD will accept inbound connections on the server socket).
diff --git a/src/include/plibc/plibc.h b/src/include/plibc/plibc.h
index 36698bf..bfc722f 100644
--- a/src/include/plibc/plibc.h
+++ b/src/include/plibc/plibc.h
@@ -553,7 +553,11 @@ char *strcasestr(const char *haystack_start, const char *needle_start);
#define CHMOD(f, p) chmod(f, p)
#define FSTAT(h, b) fstat(h, b)
#define PLIBC_KILL(p, s) kill(p, s)
+#ifdef __linux__
+ #define PIPE(h) pipe2(h, O_CLOEXEC)
+#else
#define PIPE(h) pipe(h)
+#endif
#define REMOVE(p) remove(p)
#define RENAME(o, n) rename(o, n)
#define STAT(p, b) stat(p, b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment