Remove need to move shutdown signalers
This change removes the need to move the shutdown signalers to the
ctrl-c handler. This will enable the use of the
threading::shutdown::ShutdownHandler's ownership model.
Additionally, this change allows the process to be immediately
terminated on a second ctrl-c.
@@ -18,7 +18,7 @@ use std::error::Error;
use std::fmt;
use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::Arc;
+use std::sync::{mpsc::channel, Arc};
use std::thread;
use std::time::Duration;
@@ -720,13 +720,21 @@ impl SplinterDaemon {
let (admin_shutdown_handle, service_processor_join_handle) =
Self::start_admin_service(admin_connection, admin_service, Arc::clone(&running))?;
- // Allowing possibly redundant clone of `running` since it will be needed again if the
- // `health` feature is enabled
- #[allow(clippy::redundant_clone)]
- let r = running.clone();
+ let (shutdown_tx, shutdown_rx) = channel();
ctrlc::set_handler(move || {
- info!("Received Shutdown");
- r.store(false, Ordering::SeqCst);
+ if shutdown_tx.send(()).is_err() {
+ // This was the second ctrl-c (as the receiver is dropped after the first one).
+ std::process::exit(0);
+ }
+ })
+ .expect("Error setting Ctrl-C handler");
+
+ // recv that value, ignoring the result.
+ let _ = shutdown_rx.recv();
+ drop(shutdown_rx);
+ info!("Initiating graceful shutdown (press Ctrl+C again to force)");
+
+ running.store(false, Ordering::SeqCst);
if let Err(err) = admin_shutdown_handle.shutdown() {
error!("Unable to cleanly shut down Admin service: {}", err);
@@ -739,8 +747,6 @@ impl SplinterDaemon {
network_dispatcher_shutdown.shutdown();
registry_shutdown.shutdown();
interconnect_shutdown.shutdown();
- })
- .expect("Error setting Ctrl-C handler");
#[cfg(feature = "health")]
{
