Merge pull request #988 from ethcore/rpc-exception-handling
Exception handling in RPC & WebApps
This commit is contained in:
commit
7068901649
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -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)",
|
||||
|
@ -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(),
|
||||
|
@ -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<PanicHandler>,
|
||||
pub client: Arc<Client>,
|
||||
pub sync: Arc<EthSync>,
|
||||
pub secret_store: Arc<AccountService>,
|
||||
@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<PanicHandler>,
|
||||
pub client: Arc<Client>,
|
||||
pub sync: Arc<EthSync>,
|
||||
pub secret_store: Arc<AccountService>,
|
||||
@ -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
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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);
|
||||
|
@ -10,7 +10,7 @@ authors = ["Ethcore <admin@ethcore.io"]
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
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" }
|
||||
url = "0.5"
|
||||
ethcore-rpc = { path = "../rpc" }
|
||||
|
@ -58,7 +58,7 @@ mod router;
|
||||
mod rpc;
|
||||
mod api;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::net::SocketAddr;
|
||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
||||
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
||||
@ -97,13 +97,15 @@ impl ServerBuilder {
|
||||
/// Webapps HTTP server.
|
||||
pub struct Server {
|
||||
server: Option<hyper::server::Listening>,
|
||||
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
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 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<F>(&self, handler: F) where F : Fn() -> () + Send + 'static {
|
||||
*self.panic_handler.lock().unwrap() = Some(Box::new(handler));
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Server {
|
||||
|
@ -14,28 +14,30 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// 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::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<IoHandler>) -> Box<Endpoint> {
|
||||
pub fn rpc(handler: Arc<IoHandler>, panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>) -> Box<Endpoint> {
|
||||
Box::new(RpcEndpoint {
|
||||
handler: handler,
|
||||
panic_handler: panic_handler,
|
||||
cors_domain: Some(AccessControlAllowOrigin::Null)
|
||||
})
|
||||
}
|
||||
|
||||
struct RpcEndpoint {
|
||||
handler: Arc<IoHandler>,
|
||||
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
|
||||
cors_domain: Option<AccessControlAllowOrigin>,
|
||||
}
|
||||
|
||||
impl Endpoint for RpcEndpoint {
|
||||
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