1use crate::prelude::*;
8use crate::task;
9use crate::thread;
10use signal_hook::consts::TERM_SIGNALS;
11use signal_hook::iterator::Signals;
12use std::process::exit;
13
14pub fn run<T, E>(future: impl Future<Output = Result<T, E>> + Send + 'static) -> !
20where
21  T: Send + 'static,
22  E: Display + Send + 'static,
23{
24  let task = task::start(future);
25
26  match thread::block_on(task.join()) {
27    Ok(Err(err)) => {
28      error!("The main task failed. {}", err);
29
30      thread::sleep(Duration::hz(60));
31      exit(1)
32    }
33
34    Err(err) => {
35      if let Some(value) = err.value_str() {
36        error!("The main task panicked with `{}`.", value);
37      } else {
38        error!("The main task panicked.")
39      }
40
41      thread::sleep(Duration::hz(60));
42      exit(-1)
43    }
44
45    _ => exit(0),
46  }
47}
48
49pub fn run_with<T, E, F>(func: impl FnOnce(task::CancelSignal) -> F + Send + 'static) -> !
59where
60  T: Send + 'static,
61  E: Display + Send + 'static,
62  F: Future<Output = Result<T, E>> + Send + 'static,
63{
64  let canceler = task::Canceler::new();
65  let cancel = canceler.signal();
66
67  let mut signals = Signals::new(TERM_SIGNALS).expect("Failed to register signal handler");
68
69  thread::start("af_core::run canceler", move || {
70    let mut iter = signals.into_iter();
71
72    iter.next();
73
74    warn!("The process received a termination signal. Canceling the main task…");
75
76    canceler.cancel();
77  });
78
79  run(async { func(cancel).await })
80}