diff --git a/Cargo.lock b/Cargo.lock index e082c6e6f..4f49c4e7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -305,7 +305,7 @@ dependencies = [ "ethminer 1.1.0", "ethsync 1.1.0", "jsonrpc-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 5.0.1 (git+https://github.com/debris/jsonrpc-http-server.git)", + "jsonrpc-http-server 5.1.0 (git+https://github.com/debris/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -359,7 +359,7 @@ dependencies = [ "ethcore-util 1.1.0", "hyper 0.9.0-mio (git+https://github.com/hyperium/hyper?branch=mio)", "jsonrpc-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 5.0.1 (git+https://github.com/debris/jsonrpc-http-server.git)", + "jsonrpc-http-server 5.1.0 (git+https://github.com/debris/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-status 0.2.2 (git+https://github.com/tomusdrw/parity-status.git)", "parity-wallet 0.1.1 (git+https://github.com/tomusdrw/parity-wallet.git)", @@ -560,8 +560,8 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" -version = "5.0.1" -source = "git+https://github.com/debris/jsonrpc-http-server.git#e728f2e080799b7a62b0b5cf5fa9d4ad65cd8c96" +version = "5.1.0" +source = "git+https://github.com/debris/jsonrpc-http-server.git#b32815330c191aff06a6e017ba00c10e872bb4f6" dependencies = [ "hyper 0.9.0-mio (git+https://github.com/hyperium/hyper?branch=mio)", "jsonrpc-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/parity/main.rs b/parity/main.rs index cfb365265..f6b7f5ca7 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -167,6 +167,7 @@ fn execute_client(conf: Configuration) { apis: conf.args.flag_rpcapi.clone().unwrap_or(conf.args.flag_jsonrpc_apis.clone()), cors: conf.args.flag_jsonrpc_cors.clone().or(conf.args.flag_rpccorsdomain.clone()), }, rpc::Dependencies { + panic_handler: panic_handler.clone(), client: client.clone(), sync: sync.clone(), secret_store: account_service.clone(), @@ -183,6 +184,7 @@ fn execute_client(conf: Configuration) { user: conf.args.flag_webapp_user.clone(), pass: conf.args.flag_webapp_pass.clone(), }, webapp::Dependencies { + panic_handler: panic_handler.clone(), client: client.clone(), sync: sync.clone(), secret_store: account_service.clone(), diff --git a/parity/rpc.rs b/parity/rpc.rs index e18a34947..45c102b6a 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -22,6 +22,7 @@ use ethcore::client::Client; use ethsync::EthSync; use ethminer::{Miner, ExternalMiner}; use util::RotatingLogger; +use util::panics::PanicHandler; use util::keys::store::{AccountService}; use util::network_settings::NetworkSettings; use die::*; @@ -42,6 +43,7 @@ pub struct Configuration { } pub struct Dependencies { + pub panic_handler: Arc, pub client: Arc, pub sync: Arc, pub secret_store: Arc, @@ -107,7 +109,12 @@ pub fn setup_rpc_server( match start_result { Err(RpcServerError::IoError(err)) => die_with_io_error(err), Err(e) => die!("{:?}", e), - Ok(server) => server, + Ok(server) => { + server.set_panic_handler(move || { + deps.panic_handler.notify_all("Panic in RPC thread.".to_owned()); + }); + server + }, } } diff --git a/parity/webapp.rs b/parity/webapp.rs index db18acd0a..6a5ba92ef 100644 --- a/parity/webapp.rs +++ b/parity/webapp.rs @@ -21,6 +21,7 @@ use ethcore::client::Client; use ethsync::EthSync; use ethminer::{Miner, ExternalMiner}; use util::RotatingLogger; +use util::panics::PanicHandler; use util::keys::store::{AccountService}; use util::network_settings::NetworkSettings; use die::*; @@ -39,6 +40,7 @@ pub struct Configuration { } pub struct Dependencies { + pub panic_handler: Arc, pub client: Arc, pub sync: Arc, pub secret_store: Arc, @@ -99,7 +101,7 @@ pub fn setup_webapp_server( server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); server.add_delegate(PersonalClient::new(&deps.secret_store).to_delegate()); - server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger, deps.settings).to_delegate()); + server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()); let start_result = match auth { None => { @@ -113,7 +115,12 @@ pub fn setup_webapp_server( match start_result { Err(webapp::ServerError::IoError(err)) => die_with_io_error(err), Err(e) => die!("{:?}", e), - Ok(handle) => handle, + Ok(server) => { + server.set_panic_handler(move || { + deps.panic_handler.notify_all("Panic in WebApp thread.".to_owned()); + }); + server + }, } } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 9d913e19b..f57b2bd69 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -13,7 +13,7 @@ log = "0.3" serde = "0.7.0" serde_json = "0.7.0" jsonrpc-core = "2.0" -jsonrpc-http-server = { git = "https://github.com/debris/jsonrpc-http-server.git" } +jsonrpc-http-server = { git = "https://github.com/debris/jsonrpc-http-server.git", version = "5.1.0" } ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } ethash = { path = "../ethash" } diff --git a/util/src/panics.rs b/util/src/panics.rs index 980d4fc69..854e495a3 100644 --- a/util/src/panics.rs +++ b/util/src/panics.rs @@ -85,7 +85,9 @@ impl PanicHandler { Ok(result) } - fn notify_all(&self, r: String) { + /// Notifies all listeners in case there is a panic. + /// You should use `catch_panic` instead of calling this method explicitly. + pub fn notify_all(&self, r: String) { let mut listeners = self.listeners.lock().unwrap(); for listener in listeners.deref_mut() { listener.call(&r); diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml index 18a534857..79c55862c 100644 --- a/webapp/Cargo.toml +++ b/webapp/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Ethcore , + panic_handler: Arc () + Send>>>>, } impl Server { fn start_http(addr: &SocketAddr, authorization: A, handler: Arc) -> Result { + let panic_handler = Arc::new(Mutex::new(None)); let endpoints = Arc::new(apps::all_endpoints()); let authorization = Arc::new(authorization); - let rpc_endpoint = Arc::new(rpc::rpc(handler)); + let rpc_endpoint = Arc::new(rpc::rpc(handler, panic_handler.clone())); let api = Arc::new(api::RestApi::new(endpoints.clone())); try!(hyper::Server::http(addr)) @@ -114,9 +116,17 @@ impl Server { api.clone(), authorization.clone(), )) - .map(|l| Server { server: Some(l) }) + .map(|l| Server { + server: Some(l), + panic_handler: panic_handler, + }) .map_err(ServerError::from) } + + /// Set callback for panics. + pub fn set_panic_handler(&self, handler: F) where F : Fn() -> () + Send + 'static { + *self.panic_handler.lock().unwrap() = Some(Box::new(handler)); + } } impl Drop for Server { diff --git a/webapp/src/rpc.rs b/webapp/src/rpc.rs index d80476904..51e171d8d 100644 --- a/webapp/src/rpc.rs +++ b/webapp/src/rpc.rs @@ -14,28 +14,30 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use hyper::server; use hyper::net::HttpStream; use jsonrpc_core::IoHandler; -use jsonrpc_http_server::ServerHandler; -use jsonrpc_http_server::AccessControlAllowOrigin; +use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin}; use endpoint::Endpoint; -pub fn rpc(handler: Arc) -> Box { +pub fn rpc(handler: Arc, panic_handler: Arc () + Send>>>>) -> Box { Box::new(RpcEndpoint { handler: handler, + panic_handler: panic_handler, cors_domain: Some(AccessControlAllowOrigin::Null) }) } struct RpcEndpoint { handler: Arc, + panic_handler: Arc () + Send>>>>, cors_domain: Option, } impl Endpoint for RpcEndpoint { fn to_handler(&self, _prefix: &str) -> Box> { - Box::new(ServerHandler::new(self.handler.clone(), self.cors_domain.clone())) + let panic_handler = PanicHandler { handler: self.panic_handler.clone() }; + Box::new(ServerHandler::new(self.handler.clone(), self.cors_domain.clone(), panic_handler)) } }