Merge pull request #638 from ethcore/jsonrpc_panic_handle
jsonrpc panics gracefully shutdown client
This commit is contained in:
commit
02b23d3deb
@ -43,7 +43,7 @@ use std::path::PathBuf;
|
|||||||
use env_logger::LogBuilder;
|
use env_logger::LogBuilder;
|
||||||
use ctrlc::CtrlC;
|
use ctrlc::CtrlC;
|
||||||
use util::*;
|
use util::*;
|
||||||
use util::panics::MayPanic;
|
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
use ethcore::spec::*;
|
use ethcore::spec::*;
|
||||||
use ethcore::client::*;
|
use ethcore::client::*;
|
||||||
use ethcore::service::{ClientService, NetSyncMessage};
|
use ethcore::service::{ClientService, NetSyncMessage};
|
||||||
@ -190,7 +190,7 @@ fn setup_log(init: &Option<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rpc")]
|
#[cfg(feature = "rpc")]
|
||||||
fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, url: &str, cors_domain: &str, apis: Vec<&str>) {
|
fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, url: &str, cors_domain: &str, apis: Vec<&str>) -> Option<Arc<PanicHandler>> {
|
||||||
use rpc::v1::*;
|
use rpc::v1::*;
|
||||||
|
|
||||||
let mut server = rpc::HttpServer::new(1);
|
let mut server = rpc::HttpServer::new(1);
|
||||||
@ -207,11 +207,12 @@ fn setup_rpc_server(client: Arc<Client>, sync: Arc<EthSync>, url: &str, cors_dom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server.start_async(url, cors_domain);
|
Some(server.start_async(url, cors_domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "rpc"))]
|
#[cfg(not(feature = "rpc"))]
|
||||||
fn setup_rpc_server(_client: Arc<Client>, _sync: Arc<EthSync>, _url: &str) {
|
fn setup_rpc_server(_client: Arc<Client>, _sync: Arc<EthSync>, _url: &str) -> Option<Arc<PanicHandler>> {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_version() {
|
fn print_version() {
|
||||||
@ -340,6 +341,9 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute_client(&self) {
|
fn execute_client(&self) {
|
||||||
|
// Setup panic handler
|
||||||
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
|
|
||||||
// Setup logging
|
// Setup logging
|
||||||
setup_log(&self.args.flag_logging);
|
setup_log(&self.args.flag_logging);
|
||||||
// Raise fdlimit
|
// Raise fdlimit
|
||||||
@ -366,6 +370,7 @@ impl Configuration {
|
|||||||
client_config.name = self.args.flag_identity.clone();
|
client_config.name = self.args.flag_identity.clone();
|
||||||
client_config.queue.max_mem_use = self.args.flag_queue_max_size;
|
client_config.queue.max_mem_use = self.args.flag_queue_max_size;
|
||||||
let mut service = ClientService::start(client_config, spec, net_settings, &Path::new(&self.path())).unwrap();
|
let mut service = ClientService::start(client_config, spec, net_settings, &Path::new(&self.path())).unwrap();
|
||||||
|
panic_handler.forward_from(&service);
|
||||||
let client = service.client().clone();
|
let client = service.client().clone();
|
||||||
client.set_author(self.author());
|
client.set_author(self.author());
|
||||||
client.set_extra_data(self.extra_data());
|
client.set_extra_data(self.extra_data());
|
||||||
@ -383,30 +388,36 @@ impl Configuration {
|
|||||||
let cors = self.args.flag_rpccorsdomain.as_ref().unwrap_or(&self.args.flag_jsonrpc_cors);
|
let cors = self.args.flag_rpccorsdomain.as_ref().unwrap_or(&self.args.flag_jsonrpc_cors);
|
||||||
// TODO: use this as the API list.
|
// TODO: use this as the API list.
|
||||||
let apis = self.args.flag_rpcapi.as_ref().unwrap_or(&self.args.flag_jsonrpc_apis);
|
let apis = self.args.flag_rpcapi.as_ref().unwrap_or(&self.args.flag_jsonrpc_apis);
|
||||||
setup_rpc_server(service.client(), sync.clone(), &url, cors, apis.split(",").collect());
|
let server_handler = setup_rpc_server(service.client(), sync.clone(), &url, cors, apis.split(",").collect());
|
||||||
|
if let Some(handler) = server_handler {
|
||||||
|
panic_handler.forward_from(handler.deref());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register IO handler
|
// Register IO handler
|
||||||
let io_handler = Arc::new(ClientIoHandler {
|
let io_handler = Arc::new(ClientIoHandler {
|
||||||
client: service.client(),
|
client: service.client(),
|
||||||
info: Default::default(),
|
info: Default::default(),
|
||||||
sync: sync
|
sync: sync.clone(),
|
||||||
});
|
});
|
||||||
service.io().register_handler(io_handler).expect("Error registering IO handler");
|
service.io().register_handler(io_handler).expect("Error registering IO handler");
|
||||||
|
|
||||||
// Handle exit
|
// Handle exit
|
||||||
wait_for_exit(&service);
|
wait_for_exit(panic_handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_exit(client_service: &ClientService) {
|
fn wait_for_exit(panic_handler: Arc<PanicHandler>) {
|
||||||
let exit = Arc::new(Condvar::new());
|
let exit = Arc::new(Condvar::new());
|
||||||
|
|
||||||
// Handle possible exits
|
// Handle possible exits
|
||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
CtrlC::set_handler(move || { e.notify_all(); });
|
CtrlC::set_handler(move || { e.notify_all(); });
|
||||||
|
|
||||||
|
// Handle panics
|
||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
client_service.on_panic(move |_reason| { e.notify_all(); });
|
panic_handler.on_panic(move |_reason| { e.notify_all(); });
|
||||||
|
|
||||||
// Wait for signal
|
// Wait for signal
|
||||||
let mutex = Mutex::new(());
|
let mutex = Mutex::new(());
|
||||||
|
@ -29,6 +29,9 @@ extern crate ethcore;
|
|||||||
extern crate ethsync;
|
extern crate ethsync;
|
||||||
extern crate transient_hashmap;
|
extern crate transient_hashmap;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::thread;
|
||||||
|
use util::panics::PanicHandler;
|
||||||
use self::jsonrpc_core::{IoHandler, IoDelegate};
|
use self::jsonrpc_core::{IoHandler, IoDelegate};
|
||||||
|
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
@ -36,7 +39,7 @@ pub mod v1;
|
|||||||
/// Http server.
|
/// Http server.
|
||||||
pub struct HttpServer {
|
pub struct HttpServer {
|
||||||
handler: IoHandler,
|
handler: IoHandler,
|
||||||
threads: usize
|
threads: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpServer {
|
impl HttpServer {
|
||||||
@ -44,7 +47,7 @@ impl HttpServer {
|
|||||||
pub fn new(threads: usize) -> HttpServer {
|
pub fn new(threads: usize) -> HttpServer {
|
||||||
HttpServer {
|
HttpServer {
|
||||||
handler: IoHandler::new(),
|
handler: IoHandler::new(),
|
||||||
threads: threads
|
threads: threads,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +56,18 @@ impl HttpServer {
|
|||||||
self.handler.add_delegate(delegate);
|
self.handler.add_delegate(delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start server asynchronously in new thread
|
/// Start server asynchronously in new thread and returns panic handler.
|
||||||
pub fn start_async(self, addr: &str, cors_domain: &str) {
|
pub fn start_async(self, addr: &str, cors_domain: &str) -> Arc<PanicHandler> {
|
||||||
|
let addr = addr.to_owned();
|
||||||
|
let cors_domain = cors_domain.to_owned();
|
||||||
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
|
let ph = panic_handler.clone();
|
||||||
let server = jsonrpc_http_server::Server::new(self.handler, self.threads);
|
let server = jsonrpc_http_server::Server::new(self.handler, self.threads);
|
||||||
server.start_async(addr, jsonrpc_http_server::AccessControlAllowOrigin::Value(cors_domain.to_owned()))
|
thread::Builder::new().name("jsonrpc_http".to_string()).spawn(move || {
|
||||||
|
ph.catch_panic(move || {
|
||||||
|
server.start(addr.as_ref(), jsonrpc_http_server::AccessControlAllowOrigin::Value(cors_domain));
|
||||||
|
}).unwrap()
|
||||||
|
}).expect("Error while creating jsonrpc http thread");
|
||||||
|
panic_handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user