Catch when the debug callback panicks

This commit is contained in:
Pierre Krieger 2016-05-30 10:09:04 +02:00
parent 082caeb447
commit 52f85aa270

View File

@ -33,6 +33,7 @@ use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::os::raw::{c_void, c_char};
use std::panic;
use std::ptr;
use std::sync::Arc;
@ -55,9 +56,11 @@ pub struct DebugCallback {
impl DebugCallback {
/// Initializes a debug callback.
///
/// Panicks generated by calling `user_callback` are ignored.
pub fn new<F>(instance: &Arc<Instance>, messages: MessageTypes, user_callback: F)
-> Result<DebugCallback, DebugCallbackCreationError>
where F: Fn(&Message) + 'static
where F: Fn(&Message) + 'static + panic::RefUnwindSafe
{
if !instance.loaded_extensions().ext_debug_report {
return Err(DebugCallbackCreationError::MissingExtension);
@ -72,8 +75,6 @@ impl DebugCallback {
_: i32, layer_prefix: *const c_char,
description: *const c_char, user_data: *mut c_void) -> u32
{
// FIXME: use panic::recover
unsafe {
let user_callback = user_data as *mut Box<Fn()> as *const _;
let user_callback: &Box<Fn(&Message)> = &*user_callback;
@ -97,7 +98,11 @@ impl DebugCallback {
description: description,
};
user_callback(&message);
// Since we box the closure, the type system doesn't detect that the `UnwindSafe`
// bound is enforced. Therefore we enforce it manually.
let _ = panic::catch_unwind(panic::AssertUnwindSafe(move || {
user_callback(&message);
}));
vk::FALSE
}
@ -143,7 +148,7 @@ impl DebugCallback {
#[inline]
pub fn errors_and_warnings<F>(instance: &Arc<Instance>, user_callback: F)
-> Result<DebugCallback, DebugCallbackCreationError>
where F: Fn(&Message) + 'static
where F: Fn(&Message) + 'static + panic::RefUnwindSafe
{
DebugCallback::new(instance, MessageTypes::errors_and_warnings(), user_callback)
}