config: catch and ignore panics in callbacks
This commit is contained in:
parent
86e582472d
commit
69f5be47a5
1 changed files with 21 additions and 6 deletions
|
|
@ -28,6 +28,7 @@ use {
|
||||||
future::Future,
|
future::Future,
|
||||||
mem,
|
mem,
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
|
panic::{catch_unwind, AssertUnwindSafe},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
ptr,
|
ptr,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
|
@ -49,11 +50,17 @@ fn cb<T, F: FnMut(T) + 'static>(f: F) -> Callback<T> {
|
||||||
|
|
||||||
fn run_cb<T>(name: &str, cb: &Callback<T>, t: T) {
|
fn run_cb<T>(name: &str, cb: &Callback<T>, t: T) {
|
||||||
match cb.try_borrow_mut() {
|
match cb.try_borrow_mut() {
|
||||||
Ok(mut cb) => cb(t),
|
Ok(mut cb) => ignore_panic(name, || cb(t)),
|
||||||
Err(_) => log::error!("Cannot invoke {name} callback because it is already running"),
|
Err(_) => log::error!("Cannot invoke {name} callback because it is already running"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_panic(name: &str, f: impl FnOnce()) {
|
||||||
|
if catch_unwind(AssertUnwindSafe(f)).is_err() {
|
||||||
|
log::error!("A panic occurred in a {name} callback");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Client {
|
pub(crate) struct Client {
|
||||||
configure: extern "C" fn(),
|
configure: extern "C" fn(),
|
||||||
srv_data: *const u8,
|
srv_data: *const u8,
|
||||||
|
|
@ -863,10 +870,18 @@ impl Client {
|
||||||
if let Some(fut) = fut {
|
if let Some(fut) = fut {
|
||||||
let mut fut = fut.borrow_mut();
|
let mut fut = fut.borrow_mut();
|
||||||
let fut = &mut *fut;
|
let fut = &mut *fut;
|
||||||
if let Poll::Ready(()) =
|
let res = catch_unwind(AssertUnwindSafe(|| {
|
||||||
fut.task.as_mut().poll(&mut Context::from_waker(&fut.waker))
|
fut.task.as_mut().poll(&mut Context::from_waker(&fut.waker))
|
||||||
{
|
}));
|
||||||
futures.tasks.borrow_mut().remove(&id);
|
match res {
|
||||||
|
Err(_) => {
|
||||||
|
log::error!("A task panicked");
|
||||||
|
futures.tasks.borrow_mut().remove(&id);
|
||||||
|
}
|
||||||
|
Ok(Poll::Ready(())) => {
|
||||||
|
futures.tasks.borrow_mut().remove(&id);
|
||||||
|
}
|
||||||
|
Ok(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -966,7 +981,7 @@ impl Client {
|
||||||
}
|
}
|
||||||
ServerMessage::GraphicsInitialized => {
|
ServerMessage::GraphicsInitialized => {
|
||||||
if let Some(handler) = self.on_graphics_initialized.take() {
|
if let Some(handler) = self.on_graphics_initialized.take() {
|
||||||
handler();
|
ignore_panic("graphics initialized", handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerMessage::Clear => {
|
ServerMessage::Clear => {
|
||||||
|
|
@ -992,7 +1007,7 @@ impl Client {
|
||||||
}
|
}
|
||||||
ServerMessage::DevicesEnumerated => {
|
ServerMessage::DevicesEnumerated => {
|
||||||
if let Some(handler) = self.on_devices_enumerated.take() {
|
if let Some(handler) = self.on_devices_enumerated.take() {
|
||||||
handler();
|
ignore_panic("devices enumerated", handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServerMessage::InterestReady { id, writable, res } => {
|
ServerMessage::InterestReady { id, writable, res } => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue