From d24c9b1ad9a36ad964c5d4aa516ef9e606480313 Mon Sep 17 00:00:00 2001
From: Maurice <mauricegolverdingen@gmail.com>
Date: Thu, 3 Nov 2022 11:28:27 +0100
Subject: [PATCH] Added stop signal handler

---
 Cargo.lock  | 20 ++++++++++++++++++++
 Cargo.toml  |  3 ++-
 Dockerfile  |  2 +-
 src/main.rs | 30 +++++++++++++++++++++++++-----
 4 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ca6a1a7..89017fb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -605,6 +605,7 @@ dependencies = [
  "rand",
  "rouille",
  "serde",
+ "signal-hook",
 ]
 
 [[package]]
@@ -788,6 +789,25 @@ dependencies = [
  "digest",
 ]
 
+[[package]]
+name = "signal-hook"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "sled"
 version = "0.34.7"
diff --git a/Cargo.toml b/Cargo.toml
index b04c368..120e0c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,4 +10,5 @@ kv = { version = "0.24.0", features = ["json-value"] }
 serde = { version = "1.0.145", features = ["derive"] }
 chrono = { version = "0.4.22", features = ["serde"] }
 rand = "0.8.5"
-rouille = "3.6.1"
\ No newline at end of file
+rouille = "3.6.1"
+signal-hook = "0.3.14"
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 9000a10..ad71b76 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,4 +4,4 @@ WORKDIR /app
 COPY ./target/x86_64-unknown-linux-musl/release/ /app
 COPY ./about.html /app/about.html
 
-ENTRYPOINT [ "./pastabble" ]
\ No newline at end of file
+CMD [ "./pastabble" ]
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 7e148b2..735cb5b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,10 +1,11 @@
-use std::{env, fs};
+use std::{env, fs, thread};
 
 use chrono::Utc;
 use kv::{Config, Store, Json, Bucket, Value};
 use paste::Paste;
 use rand::{Rng, distributions::Alphanumeric};
-use rouille::{Response, router, try_or_400, post_input, Request};
+use rouille::{Response, router, try_or_400, post_input, Request, Server};
+use signal_hook::{iterator::Signals, consts::{SIGINT, SIGTERM}};
 
 mod paste;
 
@@ -46,9 +47,8 @@ fn main() {
     let links = store.bucket::<String, String>(Some("links"))
         .expect("Failed to open links bucket");
     
-    // Start server
-    println!("Started PASTABBLE server on port {}", port);
-    rouille::start_server(format!("0.0.0.0:{}", port), move |req| {
+    // Create  server
+    let server = Server::new(format!("0.0.0.0:{}", port), move |req| {
         router!(req,
             (GET) (/) => {
                 Response::html(&about)
@@ -84,7 +84,27 @@ fn main() {
             },
             _ => Response::empty_404()
         )
+    }).expect("Failed to start server");
+
+    // Start server (run() or ::start_server is not able to handle graceful shutdown, hence stoppable() or poll() in loop)
+    println!("Started PASTABBLE server on {:?}", server.server_addr());
+    let (handle, stop) = server.stoppable();
+
+    // Listen for signals
+    let mut signals = Signals::new(&[SIGINT, SIGTERM]).unwrap();
+    thread::spawn(move || {
+        for sig in signals.forever() {
+            match sig {
+                _ => {
+                    println!("Received stop signal {:?}, stopping server...", sig);
+                    stop.send(()).expect("Failed to stop server");
+                }
+            }
+        }
     });
+
+    // Join server thread
+    handle.join().unwrap();
 }
 
 // Register paste handler