mirror of
https://github.com/girlbossceo/conduwuit.git
synced 2025-03-14 18:55:37 +00:00
support reloading config via SIGUSR1
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
a567e314e9
commit
2f449ba47d
7 changed files with 75 additions and 10 deletions
|
@ -1524,6 +1524,11 @@
|
|||
#
|
||||
#listening = true
|
||||
|
||||
# Enables configuration reload when the server receives SIGUSR1 on
|
||||
# supporting platforms.
|
||||
#
|
||||
#config_reload_signal = true
|
||||
|
||||
[global.tls]
|
||||
|
||||
# Path to a valid TLS certificate file.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{fmt::Write, path::PathBuf, sync::Arc};
|
||||
|
||||
use conduwuit::{info, utils::time, warn, Config, Err, Result};
|
||||
use conduwuit::{info, utils::time, warn, Err, Result};
|
||||
use ruma::events::room::message::RoomMessageEventContent;
|
||||
|
||||
use crate::admin_command;
|
||||
|
@ -32,15 +32,8 @@ pub(super) async fn reload_config(
|
|||
&self,
|
||||
path: Option<PathBuf>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
use conduwuit::config::check;
|
||||
|
||||
let path = path.as_deref().into_iter();
|
||||
let new = Config::load(path).and_then(|raw| Config::new(&raw))?;
|
||||
|
||||
let old = &self.services.server.config;
|
||||
check::reload(old, &new)?;
|
||||
|
||||
self.services.server.config.update(new)?;
|
||||
self.services.config.reload(path)?;
|
||||
|
||||
Ok(RoomMessageEventContent::text_plain("Successfully reconfigured."))
|
||||
}
|
||||
|
|
|
@ -1742,6 +1742,13 @@ pub struct Config {
|
|||
#[serde(default = "true_fn")]
|
||||
pub listening: bool,
|
||||
|
||||
/// Enables configuration reload when the server receives SIGUSR1 on
|
||||
/// supporting platforms.
|
||||
///
|
||||
/// default: true
|
||||
#[serde(default = "true_fn")]
|
||||
pub config_reload_signal: bool,
|
||||
|
||||
#[serde(flatten)]
|
||||
#[allow(clippy::zero_sized_map_values)]
|
||||
// this is a catchall, the map shouldn't be zero at runtime
|
||||
|
|
|
@ -16,6 +16,7 @@ pub(super) async fn signal(server: Arc<Server>) {
|
|||
|
||||
let mut quit = unix::signal(SignalKind::quit()).expect("SIGQUIT handler");
|
||||
let mut term = unix::signal(SignalKind::terminate()).expect("SIGTERM handler");
|
||||
let mut usr1 = unix::signal(SignalKind::user_defined1()).expect("SIGUSR1 handler");
|
||||
loop {
|
||||
trace!("Installed signal handlers");
|
||||
let sig: &'static str;
|
||||
|
@ -23,6 +24,7 @@ pub(super) async fn signal(server: Arc<Server>) {
|
|||
_ = signal::ctrl_c() => { sig = "SIGINT"; },
|
||||
_ = quit.recv() => { sig = "SIGQUIT"; },
|
||||
_ = term.recv() => { sig = "SIGTERM"; },
|
||||
_ = usr1.recv() => { sig = "SIGUSR1"; },
|
||||
}
|
||||
|
||||
warn!("Received {sig}");
|
||||
|
|
55
src/service/config/mod.rs
Normal file
55
src/service/config/mod.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::{iter, path::Path, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use conduwuit::{
|
||||
config::{check, Config},
|
||||
error, implement, Result, Server,
|
||||
};
|
||||
|
||||
pub struct Service {
|
||||
server: Arc<Server>,
|
||||
}
|
||||
|
||||
const SIGNAL: &str = "SIGUSR1";
|
||||
|
||||
#[async_trait]
|
||||
impl crate::Service for Service {
|
||||
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
||||
Ok(Arc::new(Self { server: args.server.clone() }))
|
||||
}
|
||||
|
||||
async fn worker(self: Arc<Self>) -> Result {
|
||||
while self.server.running() {
|
||||
if self.server.signal.subscribe().recv().await == Ok(SIGNAL) {
|
||||
if let Err(e) = self.handle_reload() {
|
||||
error!("Failed to reload config: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
fn handle_reload(&self) -> Result {
|
||||
if self.server.config.config_reload_signal {
|
||||
self.reload(iter::empty())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
pub fn reload<'a, I>(&self, paths: I) -> Result<Arc<Config>>
|
||||
where
|
||||
I: Iterator<Item = &'a Path>,
|
||||
{
|
||||
let old = self.server.config.clone();
|
||||
let new = Config::load(paths).and_then(|raw| Config::new(&raw))?;
|
||||
|
||||
check::reload(&old, &new)?;
|
||||
self.server.config.update(new)
|
||||
}
|
|
@ -9,6 +9,7 @@ pub mod account_data;
|
|||
pub mod admin;
|
||||
pub mod appservice;
|
||||
pub mod client;
|
||||
pub mod config;
|
||||
pub mod emergency;
|
||||
pub mod federation;
|
||||
pub mod globals;
|
||||
|
|
|
@ -10,7 +10,7 @@ use database::Database;
|
|||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
account_data, admin, appservice, client, emergency, federation, globals, key_backups,
|
||||
account_data, admin, appservice, client, config, emergency, federation, globals, key_backups,
|
||||
manager::Manager,
|
||||
media, presence, pusher, resolver, rooms, sending, server_keys, service,
|
||||
service::{Args, Map, Service},
|
||||
|
@ -21,6 +21,7 @@ pub struct Services {
|
|||
pub account_data: Arc<account_data::Service>,
|
||||
pub admin: Arc<admin::Service>,
|
||||
pub appservice: Arc<appservice::Service>,
|
||||
pub config: Arc<config::Service>,
|
||||
pub client: Arc<client::Service>,
|
||||
pub emergency: Arc<emergency::Service>,
|
||||
pub globals: Arc<globals::Service>,
|
||||
|
@ -68,6 +69,7 @@ impl Services {
|
|||
appservice: build!(appservice::Service),
|
||||
resolver: build!(resolver::Service),
|
||||
client: build!(client::Service),
|
||||
config: build!(config::Service),
|
||||
emergency: build!(emergency::Service),
|
||||
globals: build!(globals::Service),
|
||||
key_backups: build!(key_backups::Service),
|
||||
|
|
Loading…
Add table
Reference in a new issue