@@ -5,7 +5,7 @@ use std::{
55 pin:: Pin ,
66 sync:: {
77 Arc , RwLock ,
8- atomic:: { AtomicUsize , Ordering } ,
8+ atomic:: { AtomicBool , AtomicI8 , AtomicI32 , AtomicUsize , Ordering } ,
99 } ,
1010} ;
1111
@@ -51,6 +51,10 @@ mod post_scans_id;
5151mod tls;
5252use post_scans:: PostScansHandler ;
5353use post_scans_id:: { PostScansId , PostScansIdHandler } ;
54+
55+ use futures:: stream:: StreamExt ;
56+ use signal_hook:: { consts:: signal:: * , low_level:: exit} ;
57+ use signal_hook_tokio:: Signals ;
5458use tokio:: net:: TcpListener ;
5559
5660pub trait ExternalError : core:: error:: Error + Send + Sync + ' static { }
@@ -375,8 +379,34 @@ impl RuntimeBuilder<runtime_builder_states::DeleteScanIDSet> {
375379 }
376380}
377381
382+ static RUN : AtomicI32 = AtomicI32 :: new ( 0 ) ;
383+
384+ async fn handle_signals ( mut signals : Signals ) {
385+ while let Some ( signal) = signals. next ( ) . await {
386+ match signal {
387+ SIGHUP => {
388+ tracing:: info!( "Ignoring SIGHUP signal." ) ;
389+ }
390+ SIGTERM | SIGINT | SIGQUIT => {
391+ // I thought about handling it gracefully however as the request is handled in a
392+ // background task within the main loop it would just artificially complicate it
393+ // without any kind of benefit.
394+ //
395+ // The risk of corruption is relatively low, hence just exit.
396+ tracing:: info!( signal, "Exit based on signal." ) ;
397+ RUN . store ( 128 + signal, Ordering :: Relaxed ) ;
398+ }
399+ _ => unreachable ! ( ) ,
400+ }
401+ }
402+ }
403+
378404impl RuntimeBuilder < runtime_builder_states:: End > {
379- pub async fn run_blocking ( self ) -> Result < ( ) , Box < dyn std:: error:: Error + Send + Sync > > {
405+ pub async fn run_blocking ( self ) -> Result < i32 , Box < dyn std:: error:: Error + Send + Sync > > {
406+ let signals = Signals :: new ( [ SIGHUP , SIGTERM , SIGINT , SIGQUIT ] ) ?;
407+ let _handle_guard = signals. handle ( ) ;
408+ tokio:: task:: spawn ( handle_signals ( signals) ) ;
409+
380410 let scanner = Arc :: new ( self . build_scanner ( ) ) ;
381411 let tls_config = match & self . tls {
382412 Some ( x) => Some ( tls:: tls_config ( x) ?) ,
@@ -395,7 +425,7 @@ impl RuntimeBuilder<runtime_builder_states::End> {
395425 let config = Arc :: new ( tls_config. config ) ;
396426 let tls_acceptor = tokio_rustls:: TlsAcceptor :: from ( config) ;
397427
398- loop {
428+ while RUN . load ( Ordering :: Relaxed ) == 0 {
399429 let ( tcp_stream, _remote_addr) = incoming. accept ( ) . await ?;
400430 let tls_acceptor = tls_acceptor. clone ( ) ;
401431 let identifier = tls_config. client_identifier . clone ( ) ;
@@ -433,7 +463,7 @@ impl RuntimeBuilder<runtime_builder_states::End> {
433463 } else {
434464 use hyper:: server:: conn:: http1:: Builder ;
435465 tracing:: info!( "listening on http://{}" , self . listener_address) ;
436- loop {
466+ while RUN . load ( Ordering :: Relaxed ) == 0 {
437467 let ( tcp_stream, _remote_addr) = incoming. accept ( ) . await ?;
438468 let ctx = scanner. clone ( ) ;
439469 let handlers = handlers. clone ( ) ;
@@ -459,6 +489,7 @@ impl RuntimeBuilder<runtime_builder_states::End> {
459489 } ) ;
460490 }
461491 }
492+ Ok ( RUN . load ( Ordering :: Relaxed ) )
462493 }
463494}
464495
0 commit comments