extern crate clap;
use clap::{App, Arg};
+#[macro_use]
+extern crate lazy_static;
+
use grpcio::*;
-use futures::channel::oneshot;
+use futures::channel::mpsc;
use futures::executor::block_on;
+use futures::stream::StreamExt;
use bluetooth_with_facades::RootFacadeService;
-use std::io::{self, Read};
use std::sync::Arc;
-use std::thread;
+use std::sync::Mutex;
use tokio::runtime::Runtime;
+use nix::sys::signal;
+
fn main() {
+ let sigint = install_sigint();
let rt = Arc::new(Runtime::new().unwrap());
- let runtime = Arc::clone(&rt);
- runtime.block_on(async_main(rt));
+ rt.block_on(async_main(Arc::clone(&rt), sigint));
}
-async fn async_main(rt: Arc<Runtime>) {
+async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) {
let matches = App::new("bluetooth_with_facades")
.about("The bluetooth stack, with testing facades enabled and exposed via gRPC.")
.arg(
.build()
.unwrap();
- let (tx, rx) = oneshot::channel();
-
- thread::spawn(move || {
- println!("Press ENTER to exit...");
- let _ = io::stdin().read(&mut [0]).unwrap();
- tx.send(())
- });
- block_on(rx).unwrap();
+ sigint.next().await;
block_on(server.shutdown()).unwrap();
}
+
+// TODO: remove as this is a temporary nix-based hack to catch SIGINT
+fn install_sigint() -> mpsc::UnboundedReceiver<()> {
+ let (tx, rx) = mpsc::unbounded();
+ *SIGINT_TX.lock().unwrap() = Some(tx);
+
+ let sig_action = signal::SigAction::new(
+ signal::SigHandler::Handler(handle_sigint),
+ signal::SaFlags::empty(),
+ signal::SigSet::empty(),
+ );
+ unsafe {
+ signal::sigaction(signal::SIGINT, &sig_action).unwrap();
+ }
+
+ rx
+}
+
+lazy_static! {
+ static ref SIGINT_TX: Mutex<Option<mpsc::UnboundedSender<()>>> = Mutex::new(None);
+}
+
+extern "C" fn handle_sigint(_: i32) {
+ let mut sigint_tx = SIGINT_TX.lock().unwrap();
+ if let Some(tx) = &*sigint_tx {
+ println!("Stopping gRPC root server due to SIGINT");
+ tx.unbounded_send(()).unwrap();
+ }
+ *sigint_tx = None;
+}