removed panic handlers (#5895)
This commit is contained in:
parent
dc548315b8
commit
4d5280e43c
@ -95,6 +95,9 @@ secretstore = ["ethcore-secretstore"]
|
|||||||
path = "parity/main.rs"
|
path = "parity/main.rs"
|
||||||
name = "parity"
|
name = "parity"
|
||||||
|
|
||||||
|
[profile.debug]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = false
|
debug = false
|
||||||
lto = false
|
lto = false
|
||||||
|
@ -141,7 +141,6 @@ pub struct Client {
|
|||||||
block_queue: BlockQueue,
|
block_queue: BlockQueue,
|
||||||
report: RwLock<ClientReport>,
|
report: RwLock<ClientReport>,
|
||||||
import_lock: Mutex<()>,
|
import_lock: Mutex<()>,
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
verifier: Box<Verifier>,
|
verifier: Box<Verifier>,
|
||||||
miner: Arc<Miner>,
|
miner: Arc<Miner>,
|
||||||
sleep_state: Mutex<SleepState>,
|
sleep_state: Mutex<SleepState>,
|
||||||
@ -213,8 +212,6 @@ impl Client {
|
|||||||
let engine = spec.engine.clone();
|
let engine = spec.engine.clone();
|
||||||
|
|
||||||
let block_queue = BlockQueue::new(config.queue.clone(), engine.clone(), message_channel.clone(), config.verifier_type.verifying_seal());
|
let block_queue = BlockQueue::new(config.queue.clone(), engine.clone(), message_channel.clone(), config.verifier_type.verifying_seal());
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
panic_handler.forward_from(&block_queue);
|
|
||||||
|
|
||||||
let awake = match config.mode { Mode::Dark(..) | Mode::Off => false, _ => true };
|
let awake = match config.mode { Mode::Dark(..) | Mode::Off => false, _ => true };
|
||||||
|
|
||||||
@ -234,7 +231,6 @@ impl Client {
|
|||||||
block_queue: block_queue,
|
block_queue: block_queue,
|
||||||
report: RwLock::new(Default::default()),
|
report: RwLock::new(Default::default()),
|
||||||
import_lock: Mutex::new(()),
|
import_lock: Mutex::new(()),
|
||||||
panic_handler: panic_handler,
|
|
||||||
miner: miner,
|
miner: miner,
|
||||||
io_channel: Mutex::new(message_channel),
|
io_channel: Mutex::new(message_channel),
|
||||||
notify: RwLock::new(Vec::new()),
|
notify: RwLock::new(Vec::new()),
|
||||||
@ -1723,12 +1719,6 @@ impl EngineClient for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MayPanic for Client {
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
|
||||||
self.panic_handler.on_panic(closure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProvingBlockChainClient for Client {
|
impl ProvingBlockChainClient for Client {
|
||||||
fn prove_storage(&self, key1: H256, key2: H256, id: BlockId) -> Option<(Vec<Bytes>, H256)> {
|
fn prove_storage(&self, key1: H256, key2: H256, id: BlockId) -> Option<(Vec<Bytes>, H256)> {
|
||||||
self.state_at(id)
|
self.state_at(id)
|
||||||
|
@ -56,7 +56,6 @@ pub struct ClientService {
|
|||||||
io_service: Arc<IoService<ClientIoMessage>>,
|
io_service: Arc<IoService<ClientIoMessage>>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
snapshot: Arc<SnapshotService>,
|
snapshot: Arc<SnapshotService>,
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
database: Arc<Database>,
|
database: Arc<Database>,
|
||||||
_stop_guard: ::devtools::StopGuard,
|
_stop_guard: ::devtools::StopGuard,
|
||||||
}
|
}
|
||||||
@ -72,9 +71,7 @@ impl ClientService {
|
|||||||
miner: Arc<Miner>,
|
miner: Arc<Miner>,
|
||||||
) -> Result<ClientService, Error>
|
) -> Result<ClientService, Error>
|
||||||
{
|
{
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
let io_service = IoService::<ClientIoMessage>::start()?;
|
let io_service = IoService::<ClientIoMessage>::start()?;
|
||||||
panic_handler.forward_from(&io_service);
|
|
||||||
|
|
||||||
info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name()));
|
info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name()));
|
||||||
|
|
||||||
@ -109,7 +106,6 @@ impl ClientService {
|
|||||||
};
|
};
|
||||||
let snapshot = Arc::new(SnapshotService::new(snapshot_params)?);
|
let snapshot = Arc::new(SnapshotService::new(snapshot_params)?);
|
||||||
|
|
||||||
panic_handler.forward_from(&*client);
|
|
||||||
let client_io = Arc::new(ClientIoHandler {
|
let client_io = Arc::new(ClientIoHandler {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
snapshot: snapshot.clone(),
|
snapshot: snapshot.clone(),
|
||||||
@ -125,7 +121,6 @@ impl ClientService {
|
|||||||
io_service: Arc::new(io_service),
|
io_service: Arc::new(io_service),
|
||||||
client: client,
|
client: client,
|
||||||
snapshot: snapshot,
|
snapshot: snapshot,
|
||||||
panic_handler: panic_handler,
|
|
||||||
database: db,
|
database: db,
|
||||||
_stop_guard: stop_guard,
|
_stop_guard: stop_guard,
|
||||||
})
|
})
|
||||||
@ -160,12 +155,6 @@ impl ClientService {
|
|||||||
pub fn db(&self) -> Arc<KeyValueDB> { self.database.clone() }
|
pub fn db(&self) -> Arc<KeyValueDB> { self.database.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MayPanic for ClientService {
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
|
||||||
self.panic_handler.on_panic(closure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// IO interface for the Client handler
|
/// IO interface for the Client handler
|
||||||
struct ClientIoHandler {
|
struct ClientIoHandler {
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
|
@ -125,7 +125,6 @@ struct Sizes {
|
|||||||
/// A queue of items to be verified. Sits between network or other I/O and the `BlockChain`.
|
/// A queue of items to be verified. Sits between network or other I/O and the `BlockChain`.
|
||||||
/// Keeps them in the same order as inserted, minus invalid items.
|
/// Keeps them in the same order as inserted, minus invalid items.
|
||||||
pub struct VerificationQueue<K: Kind> {
|
pub struct VerificationQueue<K: Kind> {
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
more_to_verify: Arc<SCondvar>,
|
more_to_verify: Arc<SCondvar>,
|
||||||
verification: Arc<Verification<K>>,
|
verification: Arc<Verification<K>>,
|
||||||
@ -221,7 +220,6 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
message_channel: Mutex::new(message_channel),
|
message_channel: Mutex::new(message_channel),
|
||||||
});
|
});
|
||||||
let empty = Arc::new(SCondvar::new());
|
let empty = Arc::new(SCondvar::new());
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
let scale_verifiers = config.verifier_settings.scale_verifiers;
|
let scale_verifiers = config.verifier_settings.scale_verifiers;
|
||||||
|
|
||||||
let num_cpus = ::num_cpus::get();
|
let num_cpus = ::num_cpus::get();
|
||||||
@ -236,7 +234,6 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
for i in 0..max_verifiers {
|
for i in 0..max_verifiers {
|
||||||
debug!(target: "verification", "Adding verification thread #{}", i);
|
debug!(target: "verification", "Adding verification thread #{}", i);
|
||||||
|
|
||||||
let panic_handler = panic_handler.clone();
|
|
||||||
let verification = verification.clone();
|
let verification = verification.clone();
|
||||||
let engine = engine.clone();
|
let engine = engine.clone();
|
||||||
let wait = more_to_verify.clone();
|
let wait = more_to_verify.clone();
|
||||||
@ -247,7 +244,6 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
let handle = thread::Builder::new()
|
let handle = thread::Builder::new()
|
||||||
.name(format!("Verifier #{}", i))
|
.name(format!("Verifier #{}", i))
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
panic_handler.catch_panic(move || {
|
|
||||||
VerificationQueue::verify(
|
VerificationQueue::verify(
|
||||||
verification,
|
verification,
|
||||||
engine,
|
engine,
|
||||||
@ -257,7 +253,6 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
state,
|
state,
|
||||||
i,
|
i,
|
||||||
)
|
)
|
||||||
}).unwrap()
|
|
||||||
})
|
})
|
||||||
.expect("Failed to create verifier thread.");
|
.expect("Failed to create verifier thread.");
|
||||||
verifier_handles.push(handle);
|
verifier_handles.push(handle);
|
||||||
@ -265,7 +260,6 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
|
|
||||||
VerificationQueue {
|
VerificationQueue {
|
||||||
engine: engine,
|
engine: engine,
|
||||||
panic_handler: panic_handler,
|
|
||||||
ready_signal: ready_signal,
|
ready_signal: ready_signal,
|
||||||
more_to_verify: more_to_verify,
|
more_to_verify: more_to_verify,
|
||||||
verification: verification,
|
verification: verification,
|
||||||
@ -692,12 +686,6 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Kind> MayPanic for VerificationQueue<K> {
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
|
||||||
self.panic_handler.on_panic(closure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K: Kind> Drop for VerificationQueue<K> {
|
impl<K: Kind> Drop for VerificationQueue<K> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
trace!(target: "shutdown", "[VerificationQueue] Closing...");
|
trace!(target: "shutdown", "[VerificationQueue] Closing...");
|
||||||
|
@ -21,7 +21,6 @@ use std::time::{Instant, Duration};
|
|||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
use io::{PanicHandler, ForwardPanic};
|
|
||||||
use util::{ToPretty, U256, H256, Address, Hashable};
|
use util::{ToPretty, U256, H256, Address, Hashable};
|
||||||
use rlp::PayloadInfo;
|
use rlp::PayloadInfo;
|
||||||
use ethcore::service::ClientService;
|
use ethcore::service::ClientService;
|
||||||
@ -148,9 +147,6 @@ pub fn execute(cmd: BlockchainCmd) -> Result<(), String> {
|
|||||||
fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
|
fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
|
||||||
let timer = Instant::now();
|
let timer = Instant::now();
|
||||||
|
|
||||||
// Setup panic handler
|
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
|
|
||||||
// load spec file
|
// load spec file
|
||||||
let spec = cmd.spec.spec()?;
|
let spec = cmd.spec.spec()?;
|
||||||
|
|
||||||
@ -219,7 +215,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
|
|||||||
// free up the spec in memory.
|
// free up the spec in memory.
|
||||||
drop(spec);
|
drop(spec);
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
|
||||||
let client = service.client();
|
let client = service.client();
|
||||||
|
|
||||||
let mut instream: Box<io::Read> = match cmd.file_path {
|
let mut instream: Box<io::Read> = match cmd.file_path {
|
||||||
@ -390,7 +385,6 @@ fn start_client(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
|
fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
|
||||||
// Setup panic handler
|
|
||||||
let service = start_client(
|
let service = start_client(
|
||||||
cmd.dirs,
|
cmd.dirs,
|
||||||
cmd.spec,
|
cmd.spec,
|
||||||
@ -403,10 +397,8 @@ fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
|
|||||||
cmd.wal,
|
cmd.wal,
|
||||||
cmd.cache_config
|
cmd.cache_config
|
||||||
)?;
|
)?;
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
let format = cmd.format.unwrap_or_default();
|
let format = cmd.format.unwrap_or_default();
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
|
||||||
let client = service.client();
|
let client = service.client();
|
||||||
|
|
||||||
let mut out: Box<io::Write> = match cmd.file_path {
|
let mut out: Box<io::Write> = match cmd.file_path {
|
||||||
@ -433,7 +425,6 @@ fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute_export_state(cmd: ExportState) -> Result<(), String> {
|
fn execute_export_state(cmd: ExportState) -> Result<(), String> {
|
||||||
// Setup panic handler
|
|
||||||
let service = start_client(
|
let service = start_client(
|
||||||
cmd.dirs,
|
cmd.dirs,
|
||||||
cmd.spec,
|
cmd.spec,
|
||||||
@ -447,9 +438,6 @@ fn execute_export_state(cmd: ExportState) -> Result<(), String> {
|
|||||||
cmd.cache_config
|
cmd.cache_config
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
|
||||||
let client = service.client();
|
let client = service.client();
|
||||||
|
|
||||||
let mut out: Box<io::Write> = match cmd.file_path {
|
let mut out: Box<io::Write> = match cmd.file_path {
|
||||||
|
@ -21,7 +21,6 @@ use fdlimit::raise_fd_limit;
|
|||||||
use parity_rpc::{NetworkSettings, informant, is_major_importing};
|
use parity_rpc::{NetworkSettings, informant, is_major_importing};
|
||||||
use ethsync::NetworkConfiguration;
|
use ethsync::NetworkConfiguration;
|
||||||
use util::{Colour, version, Mutex, Condvar};
|
use util::{Colour, version, Mutex, Condvar};
|
||||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
|
||||||
use ethcore_logger::{Config as LogConfig, RotatingLogger};
|
use ethcore_logger::{Config as LogConfig, RotatingLogger};
|
||||||
use ethcore::miner::{StratumOptions, Stratum};
|
use ethcore::miner::{StratumOptions, Stratum};
|
||||||
use ethcore::client::{Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient};
|
use ethcore::client::{Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient};
|
||||||
@ -168,8 +167,6 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
use ethsync::{LightSyncParams, LightSync, ManageNetwork};
|
use ethsync::{LightSyncParams, LightSync, ManageNetwork};
|
||||||
use util::RwLock;
|
use util::RwLock;
|
||||||
|
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
|
|
||||||
// load spec
|
// load spec
|
||||||
let spec = cmd.spec.spec()?;
|
let spec = cmd.spec.spec()?;
|
||||||
|
|
||||||
@ -332,7 +329,7 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
});
|
});
|
||||||
|
|
||||||
// wait for ctrl-c.
|
// wait for ctrl-c.
|
||||||
Ok(wait_for_exit(panic_handler, None, None, can_restart))
|
Ok(wait_for_exit(None, None, can_restart))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> Result<(bool, Option<String>), String> {
|
pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> Result<(bool, Option<String>), String> {
|
||||||
@ -352,9 +349,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
return execute_light(cmd, can_restart, logger);
|
return execute_light(cmd, can_restart, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up panic handler
|
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
|
|
||||||
// load spec
|
// load spec
|
||||||
let spec = cmd.spec.spec()?;
|
let spec = cmd.spec.spec()?;
|
||||||
|
|
||||||
@ -517,9 +511,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
// drop the spec to free up genesis state.
|
// drop the spec to free up genesis state.
|
||||||
drop(spec);
|
drop(spec);
|
||||||
|
|
||||||
// forward panics from service
|
|
||||||
panic_handler.forward_from(&service);
|
|
||||||
|
|
||||||
// take handle to client
|
// take handle to client
|
||||||
let client = service.client();
|
let client = service.client();
|
||||||
let snapshot_service = service.snapshot_service();
|
let snapshot_service = service.snapshot_service();
|
||||||
@ -731,7 +722,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle exit
|
// Handle exit
|
||||||
let restart = wait_for_exit(panic_handler, Some(updater), Some(client), can_restart);
|
let restart = wait_for_exit(Some(updater), Some(client), can_restart);
|
||||||
|
|
||||||
info!("Finishing work, please wait...");
|
info!("Finishing work, please wait...");
|
||||||
|
|
||||||
@ -836,7 +827,6 @@ fn build_create_account_hint(spec: &SpecType, keys: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_exit(
|
fn wait_for_exit(
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
updater: Option<Arc<Updater>>,
|
updater: Option<Arc<Updater>>,
|
||||||
client: Option<Arc<Client>>,
|
client: Option<Arc<Client>>,
|
||||||
can_restart: bool
|
can_restart: bool
|
||||||
@ -847,10 +837,6 @@ fn wait_for_exit(
|
|||||||
let e = exit.clone();
|
let e = exit.clone();
|
||||||
CtrlC::set_handler(move || { e.1.notify_all(); });
|
CtrlC::set_handler(move || { e.1.notify_all(); });
|
||||||
|
|
||||||
// Handle panics
|
|
||||||
let e = exit.clone();
|
|
||||||
panic_handler.on_panic(move |_reason| { e.1.notify_all(); });
|
|
||||||
|
|
||||||
if can_restart {
|
if can_restart {
|
||||||
if let Some(updater) = updater {
|
if let Some(updater) = updater {
|
||||||
// Handle updater wanting to restart us
|
// Handle updater wanting to restart us
|
||||||
|
@ -35,8 +35,6 @@ use dir::Directories;
|
|||||||
use user_defaults::UserDefaults;
|
use user_defaults::UserDefaults;
|
||||||
use fdlimit;
|
use fdlimit;
|
||||||
|
|
||||||
use io::PanicHandler;
|
|
||||||
|
|
||||||
/// Kinds of snapshot commands.
|
/// Kinds of snapshot commands.
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
@ -133,10 +131,7 @@ fn restore_using<R: SnapshotReader>(snapshot: Arc<SnapshotService>, reader: &R,
|
|||||||
|
|
||||||
impl SnapshotCommand {
|
impl SnapshotCommand {
|
||||||
// shared portion of snapshot commands: start the client service
|
// shared portion of snapshot commands: start the client service
|
||||||
fn start_service(self) -> Result<(ClientService, Arc<PanicHandler>), String> {
|
fn start_service(self) -> Result<ClientService, String> {
|
||||||
// Setup panic handler
|
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
|
|
||||||
// load spec file
|
// load spec file
|
||||||
let spec = self.spec.spec()?;
|
let spec = self.spec.spec()?;
|
||||||
|
|
||||||
@ -196,12 +191,12 @@ impl SnapshotCommand {
|
|||||||
Arc::new(Miner::with_spec(&spec))
|
Arc::new(Miner::with_spec(&spec))
|
||||||
).map_err(|e| format!("Client service error: {:?}", e))?;
|
).map_err(|e| format!("Client service error: {:?}", e))?;
|
||||||
|
|
||||||
Ok((service, panic_handler))
|
Ok(service)
|
||||||
}
|
}
|
||||||
/// restore from a snapshot
|
/// restore from a snapshot
|
||||||
pub fn restore(self) -> Result<(), String> {
|
pub fn restore(self) -> Result<(), String> {
|
||||||
let file = self.file_path.clone();
|
let file = self.file_path.clone();
|
||||||
let (service, _panic_handler) = self.start_service()?;
|
let service = self.start_service()?;
|
||||||
|
|
||||||
warn!("Snapshot restoration is experimental and the format may be subject to change.");
|
warn!("Snapshot restoration is experimental and the format may be subject to change.");
|
||||||
warn!("On encountering an unexpected error, please ensure that you have a recent snapshot.");
|
warn!("On encountering an unexpected error, please ensure that you have a recent snapshot.");
|
||||||
@ -236,7 +231,7 @@ impl SnapshotCommand {
|
|||||||
let file_path = self.file_path.clone().ok_or("No file path provided.".to_owned())?;
|
let file_path = self.file_path.clone().ok_or("No file path provided.".to_owned())?;
|
||||||
let file_path: PathBuf = file_path.into();
|
let file_path: PathBuf = file_path.into();
|
||||||
let block_at = self.block_at;
|
let block_at = self.block_at;
|
||||||
let (service, _panic_handler) = self.start_service()?;
|
let service = self.start_service()?;
|
||||||
|
|
||||||
warn!("Snapshots are currently experimental. File formats may be subject to change.");
|
warn!("Snapshots are currently experimental. File formats may be subject to change.");
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ extern crate parking_lot;
|
|||||||
|
|
||||||
mod service;
|
mod service;
|
||||||
mod worker;
|
mod worker;
|
||||||
mod panics;
|
|
||||||
|
|
||||||
use mio::{Token};
|
use mio::{Token};
|
||||||
use mio::deprecated::{EventLoop, NotifyError};
|
use mio::deprecated::{EventLoop, NotifyError};
|
||||||
@ -137,7 +136,6 @@ pub use service::IoService;
|
|||||||
pub use service::IoChannel;
|
pub use service::IoChannel;
|
||||||
pub use service::IoManager;
|
pub use service::IoManager;
|
||||||
pub use service::TOKENS_PER_HANDLER;
|
pub use service::TOKENS_PER_HANDLER;
|
||||||
pub use panics::{PanicHandler, MayPanic, OnPanicListener, ForwardPanic};
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -171,5 +169,4 @@ mod tests {
|
|||||||
let service = IoService::<MyMessage>::start().expect("Error creating network service");
|
let service = IoService::<MyMessage>::start().expect("Error creating network service");
|
||||||
service.register_handler(Arc::new(MyHandler)).unwrap();
|
service.register_handler(Arc::new(MyHandler)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,191 +0,0 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Panic utilities
|
|
||||||
|
|
||||||
use std::thread;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::default::Default;
|
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
/// Thread-safe closure for handling possible panics
|
|
||||||
pub trait OnPanicListener: Send + Sync + 'static {
|
|
||||||
/// Invoke listener
|
|
||||||
fn call(&mut self, arg: &str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Forwards panics from child
|
|
||||||
pub trait ForwardPanic {
|
|
||||||
/// Attach `on_panic` listener to `child` and rethrow all panics
|
|
||||||
fn forward_from<S>(&self, child: &S) where S : MayPanic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait indicating that the structure catches some of the panics (most probably from spawned threads)
|
|
||||||
/// and it's possbile to be notified when one of the threads panics.
|
|
||||||
pub trait MayPanic {
|
|
||||||
/// `closure` will be invoked whenever panic in thread is caught
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PanicGuard<'a> {
|
|
||||||
handler: &'a PanicHandler,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for PanicGuard<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if thread::panicking() {
|
|
||||||
self.handler.notify_all("Panic!".to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structure that allows to catch panics and notify listeners
|
|
||||||
pub struct PanicHandler {
|
|
||||||
listeners: Mutex<Vec<Box<OnPanicListener>>>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PanicHandler {
|
|
||||||
fn default() -> Self {
|
|
||||||
PanicHandler::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PanicHandler {
|
|
||||||
/// Creates new `PanicHandler` wrapped in `Arc`
|
|
||||||
pub fn new_in_arc() -> Arc<Self> {
|
|
||||||
Arc::new(Self::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates new `PanicHandler`
|
|
||||||
pub fn new() -> Self {
|
|
||||||
PanicHandler {
|
|
||||||
listeners: Mutex::new(vec![])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invoke closure and catch any possible panics.
|
|
||||||
/// In case of panic notifies all listeners about it.
|
|
||||||
#[cfg_attr(feature="dev", allow(deprecated))]
|
|
||||||
pub fn catch_panic<G, R>(&self, g: G) -> thread::Result<R> where G: FnOnce() -> R + Send + 'static {
|
|
||||||
let _guard = PanicGuard { handler: self };
|
|
||||||
let result = g();
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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();
|
|
||||||
for mut listener in &mut **listeners {
|
|
||||||
listener.call(&r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MayPanic for PanicHandler {
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
|
||||||
self.listeners.lock().push(Box::new(closure));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ForwardPanic for Arc<PanicHandler> {
|
|
||||||
fn forward_from<S>(&self, child: &S) where S : MayPanic {
|
|
||||||
let p = self.clone();
|
|
||||||
child.on_panic(move |t| p.notify_all(t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> OnPanicListener for F
|
|
||||||
where F: FnMut(String) + Send + Sync + 'static {
|
|
||||||
fn call(&mut self, arg: &str) {
|
|
||||||
self(arg.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore] // panic forwarding doesnt work on the same thread in beta
|
|
||||||
fn should_notify_listeners_about_panic () {
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
// given
|
|
||||||
let invocations = Arc::new(RwLock::new(vec![]));
|
|
||||||
let i = invocations.clone();
|
|
||||||
let p = PanicHandler::new();
|
|
||||||
p.on_panic(move |t| i.write().push(t));
|
|
||||||
|
|
||||||
// when
|
|
||||||
p.catch_panic(|| panic!("Panic!")).unwrap_err();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert!(invocations.read()[0] == "Panic!");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore] // panic forwarding doesnt work on the same thread in beta
|
|
||||||
fn should_notify_listeners_about_panic_when_string_is_dynamic () {
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
// given
|
|
||||||
let invocations = Arc::new(RwLock::new(vec![]));
|
|
||||||
let i = invocations.clone();
|
|
||||||
let p = PanicHandler::new();
|
|
||||||
p.on_panic(move |t| i.write().push(t));
|
|
||||||
|
|
||||||
// when
|
|
||||||
p.catch_panic(|| panic!("Panic: {}", 1)).unwrap_err();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert!(invocations.read()[0] == "Panic: 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_notify_listeners_about_panic_in_other_thread () {
|
|
||||||
use std::thread;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
// given
|
|
||||||
let invocations = Arc::new(RwLock::new(vec![]));
|
|
||||||
let i = invocations.clone();
|
|
||||||
let p = PanicHandler::new();
|
|
||||||
p.on_panic(move |t| i.write().push(t));
|
|
||||||
|
|
||||||
// when
|
|
||||||
let t = thread::spawn(move ||
|
|
||||||
p.catch_panic(|| panic!("Panic!")).unwrap()
|
|
||||||
);
|
|
||||||
t.join().unwrap_err();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert!(invocations.read()[0] == "Panic!");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore] // panic forwarding doesnt work on the same thread in beta
|
|
||||||
fn should_forward_panics () {
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
// given
|
|
||||||
let invocations = Arc::new(RwLock::new(vec![]));
|
|
||||||
let i = invocations.clone();
|
|
||||||
let p = PanicHandler::new_in_arc();
|
|
||||||
p.on_panic(move |t| i.write().push(t));
|
|
||||||
|
|
||||||
let p2 = PanicHandler::new();
|
|
||||||
p.forward_from(&p2);
|
|
||||||
|
|
||||||
// when
|
|
||||||
p2.catch_panic(|| panic!("Panic!")).unwrap_err();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert!(invocations.read()[0] == "Panic!");
|
|
||||||
}
|
|
@ -24,7 +24,6 @@ use crossbeam::sync::chase_lev;
|
|||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use {IoError, IoHandler};
|
use {IoError, IoHandler};
|
||||||
use worker::{Worker, Work, WorkType};
|
use worker::{Worker, Work, WorkType};
|
||||||
use panics::*;
|
|
||||||
use parking_lot::{RwLock, Mutex};
|
use parking_lot::{RwLock, Mutex};
|
||||||
use std::sync::{Condvar as SCondvar, Mutex as SMutex};
|
use std::sync::{Condvar as SCondvar, Mutex as SMutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -191,7 +190,6 @@ pub struct IoManager<Message> where Message: Send + Sync {
|
|||||||
impl<Message> IoManager<Message> where Message: Send + Sync + Clone + 'static {
|
impl<Message> IoManager<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
/// Creates a new instance and registers it with the event loop.
|
/// Creates a new instance and registers it with the event loop.
|
||||||
pub fn start(
|
pub fn start(
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
event_loop: &mut EventLoop<IoManager<Message>>,
|
event_loop: &mut EventLoop<IoManager<Message>>,
|
||||||
handlers: Arc<RwLock<Slab<Arc<IoHandler<Message>>, HandlerId>>>
|
handlers: Arc<RwLock<Slab<Arc<IoHandler<Message>>, HandlerId>>>
|
||||||
) -> Result<(), IoError> {
|
) -> Result<(), IoError> {
|
||||||
@ -206,7 +204,6 @@ impl<Message> IoManager<Message> where Message: Send + Sync + Clone + 'static {
|
|||||||
IoChannel::new(event_loop.channel(), Arc::downgrade(&handlers)),
|
IoChannel::new(event_loop.channel(), Arc::downgrade(&handlers)),
|
||||||
work_ready.clone(),
|
work_ready.clone(),
|
||||||
work_ready_mutex.clone(),
|
work_ready_mutex.clone(),
|
||||||
panic_handler.clone(),
|
|
||||||
)
|
)
|
||||||
).collect();
|
).collect();
|
||||||
|
|
||||||
@ -417,37 +414,24 @@ impl<Message> IoChannel<Message> where Message: Send + Clone + Sync + 'static {
|
|||||||
/// General IO Service. Starts an event loop and dispatches IO requests.
|
/// General IO Service. Starts an event loop and dispatches IO requests.
|
||||||
/// 'Message' is a notification message type
|
/// 'Message' is a notification message type
|
||||||
pub struct IoService<Message> where Message: Send + Sync + Clone + 'static {
|
pub struct IoService<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
thread: Mutex<Option<JoinHandle<()>>>,
|
thread: Mutex<Option<JoinHandle<()>>>,
|
||||||
host_channel: Mutex<Sender<IoMessage<Message>>>,
|
host_channel: Mutex<Sender<IoMessage<Message>>>,
|
||||||
handlers: Arc<RwLock<Slab<Arc<IoHandler<Message>>, HandlerId>>>,
|
handlers: Arc<RwLock<Slab<Arc<IoHandler<Message>>, HandlerId>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message> MayPanic for IoService<Message> where Message: Send + Sync + Clone + 'static {
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
|
||||||
self.panic_handler.on_panic(closure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Message> IoService<Message> where Message: Send + Sync + Clone + 'static {
|
impl<Message> IoService<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
/// Starts IO event loop
|
/// Starts IO event loop
|
||||||
pub fn start() -> Result<IoService<Message>, IoError> {
|
pub fn start() -> Result<IoService<Message>, IoError> {
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
let mut config = EventLoopBuilder::new();
|
let mut config = EventLoopBuilder::new();
|
||||||
config.messages_per_tick(1024);
|
config.messages_per_tick(1024);
|
||||||
let mut event_loop = config.build().expect("Error creating event loop");
|
let mut event_loop = config.build().expect("Error creating event loop");
|
||||||
let channel = event_loop.channel();
|
let channel = event_loop.channel();
|
||||||
let panic = panic_handler.clone();
|
|
||||||
let handlers = Arc::new(RwLock::new(Slab::new(MAX_HANDLERS)));
|
let handlers = Arc::new(RwLock::new(Slab::new(MAX_HANDLERS)));
|
||||||
let h = handlers.clone();
|
let h = handlers.clone();
|
||||||
let thread = thread::spawn(move || {
|
let thread = thread::spawn(move || {
|
||||||
let p = panic.clone();
|
IoManager::<Message>::start(&mut event_loop, h).expect("Error starting IO service");
|
||||||
panic.catch_panic(move || {
|
|
||||||
IoManager::<Message>::start(p, &mut event_loop, h).expect("Error starting IO service");
|
|
||||||
}).expect("Error starting panic handler")
|
|
||||||
});
|
});
|
||||||
Ok(IoService {
|
Ok(IoService {
|
||||||
panic_handler: panic_handler,
|
|
||||||
thread: Mutex::new(Some(thread)),
|
thread: Mutex::new(Some(thread)),
|
||||||
host_channel: Mutex::new(channel),
|
host_channel: Mutex::new(channel),
|
||||||
handlers: handlers,
|
handlers: handlers,
|
||||||
|
@ -20,7 +20,6 @@ use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
|
|||||||
use crossbeam::sync::chase_lev;
|
use crossbeam::sync::chase_lev;
|
||||||
use service::{HandlerId, IoChannel, IoContext};
|
use service::{HandlerId, IoChannel, IoContext};
|
||||||
use IoHandler;
|
use IoHandler;
|
||||||
use panics::*;
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use std::sync::{Condvar as SCondvar, Mutex as SMutex};
|
use std::sync::{Condvar as SCondvar, Mutex as SMutex};
|
||||||
@ -65,7 +64,6 @@ impl Worker {
|
|||||||
channel: IoChannel<Message>,
|
channel: IoChannel<Message>,
|
||||||
wait: Arc<SCondvar>,
|
wait: Arc<SCondvar>,
|
||||||
wait_mutex: Arc<SMutex<()>>,
|
wait_mutex: Arc<SMutex<()>>,
|
||||||
panic_handler: Arc<PanicHandler>
|
|
||||||
) -> Worker
|
) -> Worker
|
||||||
where Message: Send + Sync + Clone + 'static {
|
where Message: Send + Sync + Clone + 'static {
|
||||||
let deleting = Arc::new(AtomicBool::new(false));
|
let deleting = Arc::new(AtomicBool::new(false));
|
||||||
@ -78,9 +76,7 @@ impl Worker {
|
|||||||
worker.thread = Some(thread::Builder::new().stack_size(STACK_SIZE).name(format!("IO Worker #{}", index)).spawn(
|
worker.thread = Some(thread::Builder::new().stack_size(STACK_SIZE).name(format!("IO Worker #{}", index)).spawn(
|
||||||
move || {
|
move || {
|
||||||
LOCAL_STACK_SIZE.with(|val| val.set(STACK_SIZE));
|
LOCAL_STACK_SIZE.with(|val| val.set(STACK_SIZE));
|
||||||
panic_handler.catch_panic(move || {
|
|
||||||
Worker::work_loop(stealer, channel.clone(), wait, wait_mutex.clone(), deleting)
|
Worker::work_loop(stealer, channel.clone(), wait, wait_mutex.clone(), deleting)
|
||||||
}).expect("Error starting panic handler")
|
|
||||||
})
|
})
|
||||||
.expect("Error creating worker thread"));
|
.expect("Error creating worker thread"));
|
||||||
worker
|
worker
|
||||||
|
@ -46,7 +46,6 @@ pub struct NetworkService {
|
|||||||
host_info: String,
|
host_info: String,
|
||||||
host: RwLock<Option<Arc<Host>>>,
|
host: RwLock<Option<Arc<Host>>>,
|
||||||
stats: Arc<NetworkStats>,
|
stats: Arc<NetworkStats>,
|
||||||
panic_handler: Arc<PanicHandler>,
|
|
||||||
host_handler: Arc<HostHandler>,
|
host_handler: Arc<HostHandler>,
|
||||||
config: NetworkConfiguration,
|
config: NetworkConfiguration,
|
||||||
}
|
}
|
||||||
@ -55,9 +54,7 @@ impl NetworkService {
|
|||||||
/// Starts IO event loop
|
/// Starts IO event loop
|
||||||
pub fn new(config: NetworkConfiguration) -> Result<NetworkService, NetworkError> {
|
pub fn new(config: NetworkConfiguration) -> Result<NetworkService, NetworkError> {
|
||||||
let host_handler = Arc::new(HostHandler { public_url: RwLock::new(None) });
|
let host_handler = Arc::new(HostHandler { public_url: RwLock::new(None) });
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
|
||||||
let io_service = IoService::<NetworkIoMessage>::start()?;
|
let io_service = IoService::<NetworkIoMessage>::start()?;
|
||||||
panic_handler.forward_from(&io_service);
|
|
||||||
|
|
||||||
let stats = Arc::new(NetworkStats::new());
|
let stats = Arc::new(NetworkStats::new());
|
||||||
let host_info = Host::client_version();
|
let host_info = Host::client_version();
|
||||||
@ -65,7 +62,6 @@ impl NetworkService {
|
|||||||
io_service: io_service,
|
io_service: io_service,
|
||||||
host_info: host_info,
|
host_info: host_info,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
panic_handler: panic_handler,
|
|
||||||
host: RwLock::new(None),
|
host: RwLock::new(None),
|
||||||
config: config,
|
config: config,
|
||||||
host_handler: host_handler,
|
host_handler: host_handler,
|
||||||
@ -192,9 +188,3 @@ impl NetworkService {
|
|||||||
host.as_ref().map(|ref host| host.with_context_eval(protocol, &io, action))
|
host.as_ref().map(|ref host| host.with_context_eval(protocol, &io, action))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MayPanic for NetworkService {
|
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
|
||||||
self.panic_handler.on_panic(closure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user