mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-25 11:01:10 +00:00
gstreamer: Reduce code bloat in panic handling
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1191>
This commit is contained in:
parent
3a340d0a89
commit
3e2eb6e652
7 changed files with 100 additions and 81 deletions
|
@ -135,24 +135,13 @@ impl AppSinkCallbacksBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
fn post_panic_error_message(element: &AppSink, err: &dyn std::any::Any) {
|
||||
skip_assert_initialized!();
|
||||
if let Some(cause) = err.downcast_ref::<&str>() {
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked: {}", cause]);
|
||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked: {}", cause]);
|
||||
} else {
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gpointer) {
|
||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -162,7 +151,11 @@ unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gp
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +170,7 @@ unsafe extern "C" fn trampoline_new_preroll(
|
|||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return gst::FlowReturn::Error.into_glib();
|
||||
}
|
||||
|
||||
|
@ -187,7 +180,11 @@ unsafe extern "C" fn trampoline_new_preroll(
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
|
||||
gst::FlowReturn::Error
|
||||
}
|
||||
|
@ -208,7 +205,7 @@ unsafe extern "C" fn trampoline_new_sample(
|
|||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return gst::FlowReturn::Error.into_glib();
|
||||
}
|
||||
|
||||
|
@ -218,7 +215,11 @@ unsafe extern "C" fn trampoline_new_sample(
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
|
||||
gst::FlowReturn::Error
|
||||
}
|
||||
|
@ -239,7 +240,7 @@ unsafe extern "C" fn trampoline_new_event(
|
|||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return false.into_glib();
|
||||
}
|
||||
|
||||
|
@ -249,7 +250,11 @@ unsafe extern "C" fn trampoline_new_event(
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
@ -115,17 +115,6 @@ impl AppSrcCallbacksBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
fn post_panic_error_message(element: &AppSrc, err: &dyn std::any::Any) {
|
||||
skip_assert_initialized!();
|
||||
if let Some(cause) = err.downcast_ref::<&str>() {
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked: {}", cause]);
|
||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked: {}", cause]);
|
||||
} else {
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn trampoline_need_data(
|
||||
appsrc: *mut ffi::GstAppSrc,
|
||||
length: u32,
|
||||
|
@ -136,7 +125,7 @@ unsafe extern "C" fn trampoline_need_data(
|
|||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -146,7 +135,11 @@ unsafe extern "C" fn trampoline_need_data(
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +151,7 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
|
|||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -168,7 +161,11 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +181,7 @@ unsafe extern "C" fn trampoline_seek_data(
|
|||
|
||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
||||
gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]);
|
||||
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
|
||||
return false.into_glib();
|
||||
}
|
||||
|
||||
|
@ -194,7 +191,11 @@ unsafe extern "C" fn trampoline_seek_data(
|
|||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
||||
post_panic_error_message(&element, &err);
|
||||
gst::subclass::post_panic_error_message(
|
||||
element.upcast_ref(),
|
||||
element.upcast_ref(),
|
||||
Some(err),
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
@ -667,26 +667,11 @@ impl<O: IsA<Pad>> PadExtManual for O {
|
|||
None => panic::resume_unwind(err),
|
||||
};
|
||||
|
||||
let maybe_couldnt_stop = if pad.pause_task().is_err() {
|
||||
", could not stop task"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let cause = if let Some(cause) = err.downcast_ref::<&str>() {
|
||||
cause
|
||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
||||
cause
|
||||
} else {
|
||||
"Panicked"
|
||||
};
|
||||
let _ = element.post_message(
|
||||
crate::message::Error::builder(
|
||||
crate::LibraryError::Failed,
|
||||
&format!("Panicked: {}{}", cause, maybe_couldnt_stop),
|
||||
)
|
||||
.src(&*pad)
|
||||
.build(),
|
||||
);
|
||||
if pad.pause_task().is_err() {
|
||||
crate::error!(crate::CAT_RUST, "could not stop pad task on panic");
|
||||
}
|
||||
|
||||
crate::subclass::post_panic_error_message(&element, pad.upcast_ref(), Some(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -319,6 +319,7 @@ impl<T: ElementImpl> ElementImplExt for T {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn panicked(&self) -> &atomic::AtomicBool {
|
||||
self.instance_data::<atomic::AtomicBool>(crate::Element::static_type())
|
||||
.expect("instance not initialized correctly")
|
||||
|
|
|
@ -2,33 +2,61 @@
|
|||
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{ErrorMessage, FlowReturn};
|
||||
use crate::{prelude::ElementExt, ErrorMessage, FlowReturn};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline(never)]
|
||||
pub fn post_panic_error_message(
|
||||
element: &crate::Element,
|
||||
src: &crate::Object,
|
||||
panic: Option<Box<dyn std::any::Any + Send + 'static>>,
|
||||
) {
|
||||
let cause = panic.as_ref().and_then(|err| {
|
||||
err.downcast_ref::<&str>()
|
||||
.copied()
|
||||
.or_else(|| err.downcast_ref::<String>().map(|s| s.as_str()))
|
||||
});
|
||||
|
||||
let msg = if let Some(cause) = cause {
|
||||
crate::message::Error::builder(crate::LibraryError::Failed, &format!("Panicked: {}", cause))
|
||||
.src(src)
|
||||
.build()
|
||||
} else {
|
||||
crate::message::Error::builder(crate::LibraryError::Failed, "Panicked")
|
||||
.src(src)
|
||||
.build()
|
||||
};
|
||||
|
||||
let _ = element.post_message(msg);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! panic_to_error(
|
||||
($imp:expr, $ret:expr, $code:block) => {{
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[allow(clippy::unused_unit)]
|
||||
{
|
||||
if $imp.panicked().load(Ordering::Relaxed) {
|
||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked"]));
|
||||
let panicked = $imp.panicked();
|
||||
let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);
|
||||
let element = unsafe { $crate::glib::Cast::unsafe_cast_ref::<$crate::Element>(element.as_ref()) };
|
||||
if panicked.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
$crate::subclass::post_panic_error_message(
|
||||
element,
|
||||
$crate::glib::Cast::upcast_ref::<$crate::Object>(element),
|
||||
None,
|
||||
);
|
||||
$ret
|
||||
} else {
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| $code));
|
||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code));
|
||||
|
||||
match result {
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
$imp.panicked().store(true, Ordering::Relaxed);
|
||||
if let Some(cause) = err.downcast_ref::<&str>() {
|
||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked: {}", cause]));
|
||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked: {}", cause]));
|
||||
} else {
|
||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked"]));
|
||||
}
|
||||
panicked.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
$crate::subclass::post_panic_error_message(
|
||||
element,
|
||||
$crate::glib::Cast::upcast_ref::<$crate::Object>(element),
|
||||
Some(err),
|
||||
);
|
||||
$ret
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ mod uri_handler;
|
|||
pub use self::{
|
||||
device_provider::DeviceProviderMetadata,
|
||||
element::ElementMetadata,
|
||||
error::FlowError,
|
||||
error::{post_panic_error_message, FlowError},
|
||||
plugin::{MAJOR_VERSION, MINOR_VERSION},
|
||||
task_pool::TaskPoolFunction,
|
||||
};
|
||||
|
|
|
@ -100,24 +100,23 @@ macro_rules! plugin_define(
|
|||
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
unsafe extern "C" fn plugin_init_trampoline(plugin: *mut $crate::ffi::GstPlugin) -> $crate::glib::ffi::gboolean {
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
let panic_result = std::panic::catch_unwind(
|
||||
std::panic::AssertUnwindSafe(|| super::$plugin_init(&$crate::glib::translate::from_glib_borrow(plugin)))
|
||||
);
|
||||
|
||||
let panic_result = panic::catch_unwind(AssertUnwindSafe(|| super::$plugin_init(&$crate::glib::translate::from_glib_borrow(plugin))));
|
||||
match panic_result {
|
||||
Ok(register_result) => match register_result {
|
||||
Ok(_) => $crate::glib::ffi::GTRUE,
|
||||
Err(err) => {
|
||||
let cat = $crate::DebugCategory::get("GST_PLUGIN_LOADING").unwrap();
|
||||
$crate::error!(cat, "Failed to register plugin: {}", err);
|
||||
$crate::error!($crate::CAT_PLUGIN_LOADING, "Failed to register plugin: {}", err);
|
||||
$crate::glib::ffi::GFALSE
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let cat = $crate::DebugCategory::get("GST_PLUGIN_LOADING").unwrap();
|
||||
if let Some(cause) = err.downcast_ref::<&str>() {
|
||||
$crate::error!(cat, "Failed to initialize plugin due to panic: {}", cause);
|
||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
||||
$crate::error!(cat, "Failed to initialize plugin due to panic: {}", cause);
|
||||
let cause = err.downcast_ref::<&str>().copied()
|
||||
.or_else(|| err.downcast_ref::<String>().map(|s| s.as_str()));
|
||||
if let Some(cause) = cause {
|
||||
$crate::error!($crate::PLUGIN_LOADING, "Failed to initialize plugin due to panic: {}", cause);
|
||||
} else {
|
||||
$crate::error!(cat, "Failed to initialize plugin due to panic");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue