mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
allow using other signals for graceful shutdown
This commit is contained in:
parent
f159dd5357
commit
ae66f5db43
@ -55,10 +55,7 @@ fn main() -> io::Result<()> {
|
||||
// noninteractive implies basic
|
||||
let basic = basic || noninteractive;
|
||||
|
||||
let sigusr1_signal = Arc::new(AtomicBool::new(false));
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
let _ = signal_hook::flag::register(signal_hook::consts::SIGUSR1, Arc::clone(&sigusr1_signal));
|
||||
let shutdown_signal = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let (_guards, _guards2) = if basic {
|
||||
(Vec::new(), common_frontend::init_stdout(None))
|
||||
@ -69,6 +66,16 @@ fn main() -> io::Result<()> {
|
||||
// Load settings
|
||||
let settings = settings::Settings::load();
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
{
|
||||
for signal in &settings.shutdown_signals {
|
||||
let _ = signal_hook::flag::register(
|
||||
*signal as core::ffi::c_int,
|
||||
Arc::clone(&shutdown_signal),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine folder to save server data in
|
||||
let server_data_dir = {
|
||||
let mut path = common_base::userdata_dir_workspace!();
|
||||
@ -234,7 +241,7 @@ fn main() -> io::Result<()> {
|
||||
"Server is ready to accept connections."
|
||||
);
|
||||
|
||||
let mut shutdown_coordinator = ShutdownCoordinator::new(Arc::clone(&sigusr1_signal));
|
||||
let mut shutdown_coordinator = ShutdownCoordinator::new(Arc::clone(&shutdown_signal));
|
||||
|
||||
// Set up an fps clock
|
||||
let mut clock = Clock::new(Duration::from_secs_f64(1.0 / TPS as f64));
|
||||
|
@ -6,6 +6,15 @@ use std::{
|
||||
};
|
||||
use tracing::warn;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
#[repr(i32)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum ShutdownSignal {
|
||||
SIGUSR1 = signal_hook::consts::SIGUSR1,
|
||||
SIGUSR2 = signal_hook::consts::SIGUSR2,
|
||||
SIGTERM = signal_hook::consts::SIGTERM,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Settings {
|
||||
@ -15,6 +24,7 @@ pub struct Settings {
|
||||
/// SECRET API HEADER used to access the chat api, if disabled the API is
|
||||
/// unreachable
|
||||
pub web_chat_secret: Option<String>,
|
||||
pub shutdown_signals: Vec<ShutdownSignal>,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
@ -24,6 +34,7 @@ impl Default for Settings {
|
||||
update_shutdown_message: "The server is restarting for an update".to_owned(),
|
||||
web_address: SocketAddr::from((Ipv4Addr::LOCALHOST, 14005)),
|
||||
web_chat_secret: None,
|
||||
shutdown_signals: vec![ShutdownSignal::SIGUSR1],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ use std::{
|
||||
use tracing::{error, info};
|
||||
|
||||
/// Coordinates the shutdown procedure for the server, which can be initiated by
|
||||
/// either the TUI console interface or by sending the server the SIGUSR1 signal
|
||||
/// which indicates the server is restarting due to an update.
|
||||
/// either the TUI console interface or by sending the server the SIGUSR1 (or
|
||||
/// others) signal which indicates the server is restarting due to an update.
|
||||
pub(crate) struct ShutdownCoordinator {
|
||||
/// The instant that the last shutdown message was sent, used for
|
||||
/// calculating when to send the next shutdown message
|
||||
@ -28,19 +28,19 @@ pub(crate) struct ShutdownCoordinator {
|
||||
/// The message to use for the shutdown warning message that is sent to all
|
||||
/// connected players
|
||||
shutdown_message: String,
|
||||
/// Provided by `signal_hook` to allow observation of the SIGUSR1 signal
|
||||
sigusr1_signal: Arc<AtomicBool>,
|
||||
/// Provided by `signal_hook` to allow observation of a shutdown signal
|
||||
shutdown_signal: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl ShutdownCoordinator {
|
||||
pub fn new(sigusr1_signal: Arc<AtomicBool>) -> Self {
|
||||
pub fn new(shutdown_signal: Arc<AtomicBool>) -> Self {
|
||||
Self {
|
||||
last_shutdown_msg: Instant::now(),
|
||||
msg_interval: Duration::from_secs(30),
|
||||
shutdown_initiated_at: None,
|
||||
shutdown_grace_period: Duration::from_secs(0),
|
||||
shutdown_message: String::new(),
|
||||
sigusr1_signal,
|
||||
shutdown_signal,
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,8 +81,8 @@ impl ShutdownCoordinator {
|
||||
/// returns `true` which triggers the loop in `main.rs` to break and
|
||||
/// exit the server process.
|
||||
pub fn check(&mut self, server: &mut Server, settings: &Settings) -> bool {
|
||||
// Check whether SIGUSR1 has been set
|
||||
self.check_sigusr1_signal(server, settings);
|
||||
// Check whether shutdown has been set
|
||||
self.check_shutdown_signal(server, settings);
|
||||
|
||||
// If a shutdown is in progress, check whether it's time to send another warning
|
||||
// message or shut down if the grace period has expired.
|
||||
@ -109,14 +109,14 @@ impl ShutdownCoordinator {
|
||||
false
|
||||
}
|
||||
|
||||
/// Checks whether the SIGUSR1 signal has been set, which is used to trigger
|
||||
/// a graceful shutdown for an update. [Watchtower](https://containrrr.dev/watchtower/) is configured on the main
|
||||
/// Checks whether a shutdown (SIGUSR1 by default) signal has been set,
|
||||
/// which is used to trigger a graceful shutdown for an update. [Watchtower](https://containrrr.dev/watchtower/) is configured on the main
|
||||
/// Veloren server to send SIGUSR1 instead of SIGTERM which allows us to
|
||||
/// react specifically to shutdowns that are for an update.
|
||||
/// NOTE: SIGUSR1 is not supported on Windows
|
||||
fn check_sigusr1_signal(&mut self, server: &mut Server, settings: &Settings) {
|
||||
if self.sigusr1_signal.load(Ordering::Relaxed) && self.shutdown_initiated_at.is_none() {
|
||||
info!("Received SIGUSR1 signal, initiating graceful shutdown");
|
||||
fn check_shutdown_signal(&mut self, server: &mut Server, settings: &Settings) {
|
||||
if self.shutdown_signal.load(Ordering::Relaxed) && self.shutdown_initiated_at.is_none() {
|
||||
info!("Received shutdown signal, initiating graceful shutdown");
|
||||
let grace_period =
|
||||
Duration::from_secs(u64::from(settings.update_shutdown_grace_period_secs));
|
||||
let shutdown_message = settings.update_shutdown_message.to_owned();
|
||||
@ -124,7 +124,7 @@ impl ShutdownCoordinator {
|
||||
|
||||
// Reset the SIGUSR1 signal indicator in case shutdown is aborted and we need to
|
||||
// trigger shutdown again
|
||||
self.sigusr1_signal.store(false, Ordering::Relaxed);
|
||||
self.shutdown_signal.store(false, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user