diff --git a/util/src/lib.rs b/util/src/lib.rs
index 16a25f538..b48352582 100644
--- a/util/src/lib.rs
+++ b/util/src/lib.rs
@@ -21,6 +21,7 @@
#![feature(plugin)]
#![plugin(clippy)]
#![allow(needless_range_loop, match_bool)]
+#![feature(std_panic, recover)]
//! Ethcore-util library
//!
//! ### Rust version:
@@ -54,7 +55,7 @@
//! cd parity
//! cargo build --release
//! ```
-//!
+//!
//! - OSX:
//!
//! ```bash
@@ -129,6 +130,7 @@ pub mod semantic_version;
pub mod io;
pub mod network;
pub mod log;
+pub mod panics;
pub use common::*;
pub use misc::*;
diff --git a/util/src/panics.rs b/util/src/panics.rs
new file mode 100644
index 000000000..4e1365636
--- /dev/null
+++ b/util/src/panics.rs
@@ -0,0 +1,148 @@
+// Copyright 2015, 2016 Ethcore (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 .
+
+//! Panic utilities
+
+use std::thread;
+use std::panic;
+use std::sync::Mutex;
+use std::any::Any;
+use std::ops::DerefMut;
+
+pub trait OnPanicListener: Send + Sync + 'static {
+ fn call(&mut self, arg: &T);
+}
+
+impl OnPanicListener for F
+ where F: FnMut(&T) + Send + Sync + 'static {
+ fn call(&mut self, arg: &T) {
+ self(arg)
+ }
+}
+
+pub trait ArgsConverter {
+ fn convert(&self, t: &Box) -> Option;
+}
+
+pub trait MayPanic {
+ fn on_panic(&mut self, closure: F)
+ where F: OnPanicListener;
+}
+
+pub trait PanicHandler> : MayPanic{
+ fn new(converter: C) -> Self;
+ fn catch_panic(&mut self, g: G) -> thread::Result
+ where G: FnOnce() -> R + panic::RecoverSafe;
+}
+
+
+pub struct StringConverter;
+impl ArgsConverter for StringConverter {
+ fn convert(&self, t: &Box) -> Option {
+ t.downcast_ref::<&'static str>().map(|t| t.clone().to_owned())
+ }
+}
+
+pub struct BasePanicHandler
+ where C: ArgsConverter, T: 'static {
+ converter: C,
+ listeners: Mutex>>>
+}
+
+impl BasePanicHandler
+ where C: ArgsConverter, T: 'static {
+ fn notify_all(&mut self, res: Option) {
+ if let None = res {
+ return;
+ }
+ let r = res.unwrap();
+ let mut listeners = self.listeners.lock().unwrap();
+ for listener in listeners.deref_mut() {
+ listener.call(&r);
+ }
+ }
+}
+
+impl PanicHandler for BasePanicHandler
+ where C: ArgsConverter, T: 'static {
+
+ fn new(converter: C) -> Self {
+ BasePanicHandler {
+ converter: converter,
+ listeners: Mutex::new(vec![])
+ }
+ }
+
+ fn catch_panic(&mut self, g: G) -> thread::Result
+ where G: FnOnce() -> R + panic::RecoverSafe {
+ let result = panic::recover(g);
+
+ println!("After calling function");
+ if let Err(ref e) = result {
+ let res = self.converter.convert(e);
+ println!("Got error. Notifying");
+ self.notify_all(res);
+ }
+
+ result
+ }
+}
+
+impl MayPanic for BasePanicHandler
+ where C: ArgsConverter, T: 'static {
+ fn on_panic(&mut self, closure: F)
+ where F: OnPanicListener {
+ self.listeners.lock().unwrap().push(Box::new(closure));
+ }
+}
+
+#[test]
+fn should_notify_listeners_about_panic () {
+ use std::sync::{Arc, RwLock};
+
+ // given
+ let invocations = Arc::new(RwLock::new(vec![]));
+ let i = invocations.clone();
+ let mut p = BasePanicHandler::new(StringConverter);
+ p.on_panic(move |t: &String| i.write().unwrap().push(t.clone()));
+
+ // when
+ p.catch_panic(|| panic!("Panic!"));
+
+ // then
+ assert!(invocations.read().unwrap()[0] == "Panic!");
+}
+
+#[test]
+fn should_notify_listeners_about_panic_in_other_thread () {
+ use std::thread;
+ use std::sync::{Arc, RwLock};
+
+ // given
+ let invocations = Arc::new(RwLock::new(vec![]));
+ let i = invocations.clone();
+ let mut p = BasePanicHandler::new(StringConverter);
+ p.on_panic(move |t: &String| i.write().unwrap().push(t.clone()));
+
+ // when
+ let t = thread::spawn(move ||
+ p.catch_panic(|| panic!("Panic!"))
+ );
+ t.join();
+
+ // then
+ assert!(invocations.read().unwrap()[0] == "Panic!");
+}