diff --git a/Cargo.lock b/Cargo.lock
index e05146185..8f02c75b3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1730,7 +1730,6 @@ dependencies = [
"async-trait",
"blake3",
"chrono",
- "ctrlc",
"darkfi",
"darkfi-money-contract",
"darkfi-sdk",
@@ -1740,6 +1739,8 @@ dependencies = [
"rand",
"serde",
"serde_json",
+ "signal-hook",
+ "signal-hook-async-std",
"simplelog",
"sled",
"smol",
@@ -3654,9 +3655,9 @@ dependencies = [
[[package]]
name = "signal-hook"
-version = "0.3.14"
+version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
+checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
dependencies = [
"libc",
"signal-hook-registry",
diff --git a/bin/faucetd/Cargo.toml b/bin/faucetd/Cargo.toml
index 27002c951..504e8d3da 100644
--- a/bin/faucetd/Cargo.toml
+++ b/bin/faucetd/Cargo.toml
@@ -13,7 +13,6 @@ async-std = "1.12.0"
async-trait = "0.1.64"
blake3 = "1.3.3"
chrono = "0.4.23"
-ctrlc = { version = "3.2.4", features = ["termination"] }
darkfi = {path = "../../", features = ["blockchain", "wallet", "rpc", "net", "zkas"]}
darkfi-serial = {path = "../../src/serial"}
darkfi-sdk = {path = "../../src/sdk"}
@@ -22,6 +21,8 @@ easy-parallel = "3.2.0"
log = "0.4.17"
rand = "0.8.5"
serde_json = "1.0.91"
+signal-hook = "0.3.15"
+signal-hook-async-std = "0.2.2"
simplelog = "0.12.0"
sled = "0.34.7"
smol = "1.3.0"
diff --git a/bin/faucetd/src/main.rs b/bin/faucetd/src/main.rs
index 51f2d22da..620bfe4a1 100644
--- a/bin/faucetd/src/main.rs
+++ b/bin/faucetd/src/main.rs
@@ -16,9 +16,13 @@
* along with this program. If not, see .
*/
-use std::{collections::HashMap, str::FromStr};
+use std::{collections::HashMap, path::PathBuf, str::FromStr};
-use async_std::sync::{Arc, Mutex, RwLock};
+use async_std::{
+ stream::StreamExt,
+ sync::{Arc, Mutex, RwLock},
+ task,
+};
use async_trait::async_trait;
use chrono::Utc;
use darkfi::{
@@ -47,6 +51,8 @@ use darkfi_serial::{deserialize, serialize, Encodable};
use log::{debug, error, info};
use rand::rngs::OsRng;
use serde_json::{json, Value};
+use signal_hook::consts::{SIGHUP, SIGINT, SIGQUIT, SIGTERM};
+use signal_hook_async_std::Signals;
use sqlx::Row;
use structopt_toml::{serde::Deserialize, structopt::StructOpt, StructOptToml};
use url::Url;
@@ -72,7 +78,11 @@ use darkfi::{
},
server::{listen_and_serve, RequestHandler},
},
- util::{async_util::sleep, parse::decode_base10, path::expand_path},
+ util::{
+ async_util::sleep,
+ parse::decode_base10,
+ path::{expand_path, get_config_path},
+ },
wallet::{walletdb::init_wallet, WalletPtr},
Error, Result,
};
@@ -512,16 +522,36 @@ async fn prune_airdrop_map(map: Arc>>, timeout: i64
}
}
+async fn handle_signals(
+ mut signals: Signals,
+ _cfg_path: PathBuf,
+ term_tx: smol::channel::Sender<()>,
+) {
+ debug!("Started signal handler");
+ while let Some(signal) = signals.next().await {
+ match signal {
+ SIGHUP => {
+ info!("Caught SIGHUP");
+ }
+
+ SIGTERM | SIGINT | SIGQUIT => {
+ term_tx.send(()).await.unwrap();
+ }
+
+ _ => unreachable!(),
+ }
+ }
+}
+
async_daemonize!(realmain);
async fn realmain(args: Args, ex: Arc>) -> Result<()> {
- // We use this handler to block this function after detaching all
- // tasks, and to catch a shutdown signal, where we can clean up and
- // exit gracefully.
- let (signal, shutdown) = smol::channel::bounded::<()>(1);
- ctrlc::set_handler(move || {
- async_std::task::block_on(signal.send(())).unwrap();
- })
- .unwrap();
+ let cfg_path = get_config_path(args.config, CONFIG_FILE)?;
+
+ // Signal handling for config reload and graceful termination.
+ let signals = Signals::new([SIGHUP, SIGTERM, SIGINT, SIGQUIT])?;
+ let handle = signals.handle();
+ let (term_tx, term_rx) = smol::channel::bounded::<()>(1);
+ let signals_task = task::spawn(handle_signals(signals, cfg_path.clone(), term_tx));
// Initialize or load wallet
let wallet = init_wallet(&args.wallet_path, &args.wallet_pass).await?;
@@ -653,10 +683,12 @@ async fn realmain(args: Args, ex: Arc>) -> Result<()> {
Err(e) => error!("Failed syncing blockchain: {}", e),
}
- // Wait for SIGINT
- shutdown.recv().await?;
+ // Wait for termination signal
+ term_rx.recv().await?;
print!("\r");
info!("Caught termination signal, cleaning up and exiting...");
+ handle.close();
+ signals_task.await;
info!("Flushing database...");
let flushed_bytes = sled_db.flush_async().await?;