about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-10-26 18:14:10 -0400
committerJune McEnroe <june@causal.agency>2019-10-26 18:14:10 -0400
commitea0a9f3c813eefd5d498a00c0c9d9785bbe5e2b2 (patch)
treec68217479423583a5e21546965a7a02a026b34c9
parentRequire PASS before USER (diff)
downloadpounce-ea0a9f3c813eefd5d498a00c0c9d9785bbe5e2b2.tar.gz
pounce-ea0a9f3c813eefd5d498a00c0c9d9785bbe5e2b2.zip
Implement graceful shutdown
-rw-r--r--bounce.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/bounce.c b/bounce.c
index 8d9a4b5..0c2d1d7 100644
--- a/bounce.c
+++ b/bounce.c
@@ -16,8 +16,10 @@
 
 #include <assert.h>
 #include <err.h>
+#include <errno.h>
 #include <limits.h>
 #include <poll.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,6 +30,11 @@
 
 #include "bounce.h"
 
+static volatile sig_atomic_t signals[NSIG];
+static void signalHandler(int signal) {
+	signals[signal] = 1;
+}
+
 static struct {
 	struct pollfd *fds;
 	struct Client **clients;
@@ -148,8 +155,16 @@ int main(int argc, char *argv[]) {
 	}
 	eventAdd(server, NULL);
 
+	signal(SIGINT, signalHandler);
+	signal(SIGTERM, signalHandler);
+
 	size_t clients = 0;
-	while (0 < poll(event.fds, event.len, -1)) {
+	for (;;) {
+		int nfds = poll(event.fds, event.len, -1);
+		if (nfds < 0 && errno != EINTR) err(EX_IOERR, "poll");
+		if (signals[SIGINT] || signals[SIGTERM]) break;
+		if (nfds < 0) continue;
+
 		for (size_t i = 0; i < event.len; ++i) {
 			short revents = event.fds[i].revents;
 			if (!revents) continue;
@@ -158,6 +173,8 @@ int main(int argc, char *argv[]) {
 				int fd;
 				struct tls *tls = listenAccept(&fd, event.fds[i].fd);
 				eventAdd(fd, clientAlloc(tls));
+				// FIXME: This should only be done after a successful client
+				// registration.
 				if (!clients++) serverFormat("AWAY\r\n");
 				continue;
 			}
@@ -192,5 +209,13 @@ int main(int argc, char *argv[]) {
 			}
 		}
 	}
-	err(EX_IOERR, "poll");
+
+	serverFormat("QUIT\r\n");
+	for (size_t i = 0; i < event.len; ++i) {
+		if (event.clients[i]) {
+			clientFormat(event.clients[i], "ERROR :Disconnecting\r\n");
+			clientFree(event.clients[i]);
+		}
+		close(event.fds[i].fd);
+	}
 }