Skip to content

Commit

Permalink
Merge pull request #241 from hellerve/handle-signals
Browse files Browse the repository at this point in the history
Reload TALs on SIGHUP
  • Loading branch information
partim authored Nov 26, 2019
2 parents 8289690 + 25cd875 commit a5c3083
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 13 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ build = "build.rs"
bytes = "^0.4"
chrono = "^0.4"
clap = "^2.0"
crossbeam-channel = "^0.4"
crossbeam-queue = "^0.1"
crossbeam-utils = "^0.6"
derive_more = "^0.15"
Expand All @@ -32,6 +33,7 @@ reqwest = { version = "^0.9.19", default-features = false, features = [ "rustls
ring = "^0.14"
rpki = "^0.8.0"
serde = "^1.0"
signal-hook = "^0.1.11"
slab = "^0.4"
tempfile = "^3.1"
tokio = "^0.1"
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ pub mod slurm;
pub mod utils;
pub mod validity;

#[cfg(not(windows))]
#[macro_use]
extern crate crossbeam_channel;
92 changes: 79 additions & 13 deletions src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use crate::rtr::rtr_listener;
use crate::slurm::LocalExceptions;
use crate::validity::RouteValidity;


//------------ Operation -----------------------------------------------------

/// The command to execute.
Expand Down Expand Up @@ -356,7 +355,6 @@ impl Server {
/// Runs the command.
pub fn run(self, mut config: Config) -> Result<(), ExitError> {
let mut repo = Repository::new(&config, false, true)?;
let idle = IdleWait::new()?; // Create early to fail early.
config.switch_logging(self.detach)?;

let history = OriginsHistory::new(config.history_size, config.refresh);
Expand All @@ -375,6 +373,7 @@ impl Server {
}
};
runtime.spawn(rtr).spawn(http);
let signal = SignalWait::new(&mut runtime)?;

loop {
history.mark_update_start();
Expand Down Expand Up @@ -404,8 +403,19 @@ impl Server {
info!("Sending out notifications.");
notify.notify();
}
if !idle.wait(history.refresh_wait()) {
break;
match signal.wait(history.refresh_wait()) {
UserSignal::NoSignal => {},
UserSignal::ReloadTALs => {
match repo.reload_tals(&config) {
Ok(_) => {
info!("Reloaded TALs at user request.");
},
Err(_) => {
error!("Reloading TALs failed, shutting down.");
break;
}
}
}
}
}

Expand Down Expand Up @@ -951,28 +961,84 @@ impl Man {
}


//------------ IdleWait ------------------------------------------------------
//------------ SignalWait ------------------------------------------------------

/// Wait for the next validation run or a user telling us to quit.
#[allow(dead_code)]
enum UserSignal {
NoSignal,
ReloadTALs,
}

/// Wait for the next validation run or a user telling us to quit or reload.
///
/// This is going to receive a proper impl on Unix and possibly Windows.
struct IdleWait;
#[cfg(not(windows))]
struct SignalWait {
chan: crossbeam_channel::Receiver<i32>
}

#[cfg(not(windows))]
impl SignalWait {
pub fn new(mut runtime: &mut tokio::runtime::Runtime) -> Result<Self, Error> {
let chan = Self::create_signal_notifier(&mut runtime)?;
Ok(SignalWait{chan})
}

fn create_signal_notifier(
runtime: &mut tokio::runtime::Runtime
) -> Result<crossbeam_channel::Receiver<i32>, Error> {
let (s, r) = crossbeam_channel::bounded(100);
let signals = match signal_hook::iterator::Signals::new(&[signal_hook::SIGUSR1]) {
Ok(r) => r,
Err(err) => {
error!("Attaching signals failed: {}", err);
return Err(Error)
}
};
runtime.spawn(futures::future::lazy(move || {
for signal in signals.forever() {
if s.send(signal).is_err() {
break;
}
}
Ok(())
}));
Ok(r)
}

impl IdleWait {
pub fn new() -> Result<Self, Error> {
Ok(IdleWait)
/// Waits for the next thing to do.
///
/// Returns what to do.
// Clippy seems to have problems understanding the select! macro
#[allow(clippy::needless_return)]
pub fn wait(&self, timeout: Duration) -> UserSignal {
select! {
recv(self.chan) -> _ => {
return UserSignal::ReloadTALs;
},
recv(crossbeam_channel::after(timeout)) -> _ => { return UserSignal::NoSignal; }
};
}
}

#[cfg(windows)]
struct SignalWait;

#[cfg(windows)]
impl SignalWait {
pub fn new(_runtime: &mut tokio::runtime::Runtime) -> Result<Self, Error> {
Ok(SignalWait)
}

/// Waits for the next thing to do.
///
/// Returns whether to continue working.
pub fn wait(&self, timeout: Duration) -> bool {
pub fn wait(&self, timeout: Duration) -> UserSignal {
std::thread::sleep(timeout);
true
UserSignal::NoSignal
}
}


//------------ Error ---------------------------------------------------------

/// An error has occurred during operation.
Expand Down
6 changes: 6 additions & 0 deletions src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ impl Repository {
})
}

/// Reloads the TAL files based on the config object.
pub fn reload_tals(&mut self, config: &Config) -> Result<(), Error> {
self.tals = Self::load_tals(&config.tal_dir)?;
Ok(())
}

/// Loads the TAL files from the given directory.
fn load_tals(tal_dir: &Path) -> Result<Vec<Tal>, Error> {
let mut res = Vec::new();
Expand Down

0 comments on commit a5c3083

Please sign in to comment.