11mod config;
22
3- use std:: { env, sync:: Arc } ;
3+ use std:: { env, panic :: PanicInfo , sync:: Arc } ;
44
55use api:: { run_server, DefaultAPIAdapter } ;
6+ use backtrace:: Backtrace ;
67use config:: SparkConfig ;
78use storage:: { SmtManager , TransactionHistory } ;
9+ #[ cfg( unix) ]
10+ use tokio:: signal:: unix as os_impl;
811
912#[ tokio:: main]
1013async fn main ( ) {
@@ -14,9 +17,63 @@ async fn main() {
1417 let rdb = Arc :: new ( TransactionHistory :: new ( & config. rdb_url ) . await ) ;
1518 let kvdb = Arc :: new ( SmtManager :: new ( & config. kvdb_path ) ) ;
1619 let api_adapter = Arc :: new ( DefaultAPIAdapter :: new ( rdb, kvdb) ) ;
17- let _handle = run_server ( api_adapter, config. rpc_listen_address )
20+ let handle = run_server ( api_adapter, config. rpc_listen_address )
1821 . await
1922 . unwrap ( ) ;
2023
21- println ! ( "Hello, world!" ) ;
24+ tokio:: spawn ( handle. stopped ( ) ) ;
25+
26+ set_ctrl_c_handle ( ) . await ;
27+ }
28+
29+ async fn set_ctrl_c_handle ( ) {
30+ let ctrl_c_handler = tokio:: spawn ( async {
31+ #[ cfg( windows) ]
32+ let _ = tokio:: signal:: ctrl_c ( ) . await ;
33+ #[ cfg( unix) ]
34+ {
35+ let mut sigtun_int = os_impl:: signal ( os_impl:: SignalKind :: interrupt ( ) ) . unwrap ( ) ;
36+ let mut sigtun_term = os_impl:: signal ( os_impl:: SignalKind :: terminate ( ) ) . unwrap ( ) ;
37+ tokio:: select! {
38+ _ = sigtun_int. recv( ) => { }
39+ _ = sigtun_term. recv( ) => { }
40+ } ;
41+ }
42+ } ) ;
43+
44+ // register channel of panic
45+ let ( panic_sender, mut panic_receiver) = tokio:: sync:: mpsc:: channel :: < ( ) > ( 1 ) ;
46+
47+ std:: panic:: set_hook ( Box :: new ( move |info : & PanicInfo | {
48+ let panic_sender = panic_sender. clone ( ) ;
49+ panic_log ( info) ;
50+ panic_sender. try_send ( ( ) ) . expect ( "panic_receiver is droped" ) ;
51+ } ) ) ;
52+
53+ tokio:: select! {
54+ _ = ctrl_c_handler => { log:: info!( "ctrl + c is pressed, quit." ) } ,
55+ _ = panic_receiver. recv( ) => { log:: info!( "child thread panic, quit." ) } ,
56+ } ;
57+ }
58+
59+ fn panic_log ( info : & PanicInfo ) {
60+ let backtrace = Backtrace :: new ( ) ;
61+ let thread = std:: thread:: current ( ) ;
62+ let name = thread. name ( ) . unwrap_or ( "unnamed" ) ;
63+ let location = info. location ( ) . unwrap ( ) ; // The current implementation always returns Some
64+ let msg = match info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
65+ Some ( s) => * s,
66+ None => match info. payload ( ) . downcast_ref :: < String > ( ) {
67+ Some ( s) => & * * s,
68+ None => "Box<Any>" ,
69+ } ,
70+ } ;
71+ log:: error!(
72+ target: "panic" , "thread '{}' panicked at '{}': {}:{} {:?}" ,
73+ name,
74+ msg,
75+ location. file( ) ,
76+ location. line( ) ,
77+ backtrace,
78+ ) ;
2279}
0 commit comments