1
1
mod config;
2
2
3
- use std:: { env, sync:: Arc } ;
3
+ use std:: { env, panic :: PanicInfo , sync:: Arc } ;
4
4
5
5
use api:: { run_server, DefaultAPIAdapter } ;
6
+ use backtrace:: Backtrace ;
6
7
use config:: SparkConfig ;
7
8
use storage:: { SmtManager , TransactionHistory } ;
9
+ #[ cfg( unix) ]
10
+ use tokio:: signal:: unix as os_impl;
8
11
9
12
#[ tokio:: main]
10
13
async fn main ( ) {
@@ -14,9 +17,63 @@ async fn main() {
14
17
let rdb = Arc :: new ( TransactionHistory :: new ( & config. rdb_url ) . await ) ;
15
18
let kvdb = Arc :: new ( SmtManager :: new ( & config. kvdb_path ) ) ;
16
19
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 )
18
21
. await
19
22
. unwrap ( ) ;
20
23
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
+ ) ;
22
79
}
0 commit comments