Exception handling in RPC & WebApps
This commit is contained in:
parent
11b0daf6cb
commit
8956d7e02b
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -300,7 +300,7 @@ dependencies = [
|
|||||||
"ethminer 1.1.0",
|
"ethminer 1.1.0",
|
||||||
"ethsync 1.1.0",
|
"ethsync 1.1.0",
|
||||||
"jsonrpc-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -354,7 +354,7 @@ dependencies = [
|
|||||||
"ethcore-util 1.1.0",
|
"ethcore-util 1.1.0",
|
||||||
"hyper 0.9.0-mio (git+https://github.com/hyperium/hyper?branch=mio)",
|
"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-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",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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-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)",
|
"parity-wallet 0.1.1 (git+https://github.com/tomusdrw/parity-wallet.git)",
|
||||||
@ -545,8 +545,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-http-server"
|
name = "jsonrpc-http-server"
|
||||||
version = "5.0.1"
|
version = "5.1.0"
|
||||||
source = "git+https://github.com/debris/jsonrpc-http-server.git#e728f2e080799b7a62b0b5cf5fa9d4ad65cd8c96"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper 0.9.0-mio (git+https://github.com/hyperium/hyper?branch=mio)",
|
"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-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -166,6 +166,7 @@ fn execute_client(conf: Configuration) {
|
|||||||
apis: conf.args.flag_rpcapi.clone().unwrap_or(conf.args.flag_jsonrpc_apis.clone()),
|
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()),
|
cors: conf.args.flag_jsonrpc_cors.clone().or(conf.args.flag_rpccorsdomain.clone()),
|
||||||
}, rpc::Dependencies {
|
}, rpc::Dependencies {
|
||||||
|
panic_handler: panic_handler.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
sync: sync.clone(),
|
sync: sync.clone(),
|
||||||
secret_store: account_service.clone(),
|
secret_store: account_service.clone(),
|
||||||
@ -181,6 +182,7 @@ fn execute_client(conf: Configuration) {
|
|||||||
user: conf.args.flag_webapp_user.clone(),
|
user: conf.args.flag_webapp_user.clone(),
|
||||||
pass: conf.args.flag_webapp_pass.clone(),
|
pass: conf.args.flag_webapp_pass.clone(),
|
||||||
}, webapp::Dependencies {
|
}, webapp::Dependencies {
|
||||||
|
panic_handler: panic_handler.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
sync: sync.clone(),
|
sync: sync.clone(),
|
||||||
secret_store: account_service.clone(),
|
secret_store: account_service.clone(),
|
||||||
|
@ -22,6 +22,7 @@ use ethcore::client::Client;
|
|||||||
use ethsync::EthSync;
|
use ethsync::EthSync;
|
||||||
use ethminer::Miner;
|
use ethminer::Miner;
|
||||||
use util::RotatingLogger;
|
use util::RotatingLogger;
|
||||||
|
use util::panics::PanicHandler;
|
||||||
use util::keys::store::{AccountService};
|
use util::keys::store::{AccountService};
|
||||||
use util::network_settings::NetworkSettings;
|
use util::network_settings::NetworkSettings;
|
||||||
use die::*;
|
use die::*;
|
||||||
@ -42,6 +43,7 @@ pub struct Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Dependencies {
|
pub struct Dependencies {
|
||||||
|
pub panic_handler: Arc<PanicHandler>,
|
||||||
pub client: Arc<Client>,
|
pub client: Arc<Client>,
|
||||||
pub sync: Arc<EthSync>,
|
pub sync: Arc<EthSync>,
|
||||||
pub secret_store: Arc<AccountService>,
|
pub secret_store: Arc<AccountService>,
|
||||||
@ -106,7 +108,12 @@ pub fn setup_rpc_server(
|
|||||||
match start_result {
|
match start_result {
|
||||||
Err(RpcServerError::IoError(err)) => die_with_io_error(err),
|
Err(RpcServerError::IoError(err)) => die_with_io_error(err),
|
||||||
Err(e) => die!("{:?}", e),
|
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
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ use ethcore::client::Client;
|
|||||||
use ethsync::EthSync;
|
use ethsync::EthSync;
|
||||||
use ethminer::Miner;
|
use ethminer::Miner;
|
||||||
use util::RotatingLogger;
|
use util::RotatingLogger;
|
||||||
|
use util::panics::PanicHandler;
|
||||||
use util::keys::store::{AccountService};
|
use util::keys::store::{AccountService};
|
||||||
use util::network_settings::NetworkSettings;
|
use util::network_settings::NetworkSettings;
|
||||||
use die::*;
|
use die::*;
|
||||||
@ -39,6 +40,7 @@ pub struct Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Dependencies {
|
pub struct Dependencies {
|
||||||
|
pub panic_handler: Arc<PanicHandler>,
|
||||||
pub client: Arc<Client>,
|
pub client: Arc<Client>,
|
||||||
pub sync: Arc<EthSync>,
|
pub sync: Arc<EthSync>,
|
||||||
pub secret_store: Arc<AccountService>,
|
pub secret_store: Arc<AccountService>,
|
||||||
@ -98,7 +100,7 @@ pub fn setup_webapp_server(
|
|||||||
server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner).to_delegate());
|
server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner).to_delegate());
|
||||||
server.add_delegate(EthFilterClient::new(&deps.client, &deps.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(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 {
|
let start_result = match auth {
|
||||||
None => {
|
None => {
|
||||||
@ -112,7 +114,12 @@ pub fn setup_webapp_server(
|
|||||||
match start_result {
|
match start_result {
|
||||||
Err(webapp::ServerError::IoError(err)) => die_with_io_error(err),
|
Err(webapp::ServerError::IoError(err)) => die_with_io_error(err),
|
||||||
Err(e) => die!("{:?}", e),
|
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
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ log = "0.3"
|
|||||||
serde = "0.7.0"
|
serde = "0.7.0"
|
||||||
serde_json = "0.7.0"
|
serde_json = "0.7.0"
|
||||||
jsonrpc-core = "2.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-util = { path = "../util" }
|
||||||
ethcore = { path = "../ethcore" }
|
ethcore = { path = "../ethcore" }
|
||||||
ethash = { path = "../ethash" }
|
ethash = { path = "../ethash" }
|
||||||
|
@ -85,7 +85,9 @@ impl PanicHandler {
|
|||||||
Ok(result)
|
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();
|
let mut listeners = self.listeners.lock().unwrap();
|
||||||
for listener in listeners.deref_mut() {
|
for listener in listeners.deref_mut() {
|
||||||
listener.call(&r);
|
listener.call(&r);
|
||||||
|
@ -10,7 +10,7 @@ authors = ["Ethcore <admin@ethcore.io"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
jsonrpc-core = "2.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" }
|
||||||
hyper = { default-features = false, git = "https://github.com/hyperium/hyper", branch = "mio" }
|
hyper = { default-features = false, git = "https://github.com/hyperium/hyper", branch = "mio" }
|
||||||
url = "0.5"
|
url = "0.5"
|
||||||
ethcore-rpc = { path = "../rpc" }
|
ethcore-rpc = { path = "../rpc" }
|
||||||
|
@ -58,7 +58,7 @@ mod router;
|
|||||||
mod rpc;
|
mod rpc;
|
||||||
mod api;
|
mod api;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
use jsonrpc_core::{IoHandler, IoDelegate};
|
||||||
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
||||||
@ -97,13 +97,15 @@ impl ServerBuilder {
|
|||||||
/// Webapps HTTP server.
|
/// Webapps HTTP server.
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
server: Option<hyper::server::Listening>,
|
server: Option<hyper::server::Listening>,
|
||||||
|
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
fn start_http<A: Authorization + 'static>(addr: &SocketAddr, authorization: A, handler: Arc<IoHandler>) -> Result<Server, ServerError> {
|
fn start_http<A: Authorization + 'static>(addr: &SocketAddr, authorization: A, handler: Arc<IoHandler>) -> Result<Server, ServerError> {
|
||||||
|
let panic_handler = Arc::new(Mutex::new(None));
|
||||||
let endpoints = Arc::new(apps::all_endpoints());
|
let endpoints = Arc::new(apps::all_endpoints());
|
||||||
let authorization = Arc::new(authorization);
|
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()));
|
let api = Arc::new(api::RestApi::new(endpoints.clone()));
|
||||||
|
|
||||||
try!(hyper::Server::http(addr))
|
try!(hyper::Server::http(addr))
|
||||||
@ -114,9 +116,17 @@ impl Server {
|
|||||||
api.clone(),
|
api.clone(),
|
||||||
authorization.clone(),
|
authorization.clone(),
|
||||||
))
|
))
|
||||||
.map(|l| Server { server: Some(l) })
|
.map(|l| Server {
|
||||||
|
server: Some(l),
|
||||||
|
panic_handler: panic_handler,
|
||||||
|
})
|
||||||
.map_err(ServerError::from)
|
.map_err(ServerError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set callback for panics.
|
||||||
|
pub fn set_panic_handler<F>(&self, handler: F) where F : Fn() -> () + Send + 'static {
|
||||||
|
*self.panic_handler.lock().unwrap() = Some(Box::new(handler));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Server {
|
impl Drop for Server {
|
||||||
|
@ -14,28 +14,30 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
use hyper::server;
|
use hyper::server;
|
||||||
use hyper::net::HttpStream;
|
use hyper::net::HttpStream;
|
||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
use jsonrpc_http_server::ServerHandler;
|
use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin};
|
||||||
use jsonrpc_http_server::AccessControlAllowOrigin;
|
|
||||||
use endpoint::Endpoint;
|
use endpoint::Endpoint;
|
||||||
|
|
||||||
pub fn rpc(handler: Arc<IoHandler>) -> Box<Endpoint> {
|
pub fn rpc(handler: Arc<IoHandler>, panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>) -> Box<Endpoint> {
|
||||||
Box::new(RpcEndpoint {
|
Box::new(RpcEndpoint {
|
||||||
handler: handler,
|
handler: handler,
|
||||||
|
panic_handler: panic_handler,
|
||||||
cors_domain: Some(AccessControlAllowOrigin::Null)
|
cors_domain: Some(AccessControlAllowOrigin::Null)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RpcEndpoint {
|
struct RpcEndpoint {
|
||||||
handler: Arc<IoHandler>,
|
handler: Arc<IoHandler>,
|
||||||
|
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
|
||||||
cors_domain: Option<AccessControlAllowOrigin>,
|
cors_domain: Option<AccessControlAllowOrigin>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Endpoint for RpcEndpoint {
|
impl Endpoint for RpcEndpoint {
|
||||||
fn to_handler(&self, _prefix: &str) -> Box<server::Handler<HttpStream>> {
|
fn to_handler(&self, _prefix: &str) -> Box<server::Handler<HttpStream>> {
|
||||||
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user