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}