forked from mirrors/gstreamer-rs
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) {
|
unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gpointer) {
|
||||||
let callbacks = callbacks as *mut AppSinkCallbacks;
|
let callbacks = callbacks as *mut AppSinkCallbacks;
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
||||||
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +151,11 @@ unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gp
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
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();
|
return gst::FlowReturn::Error.into_glib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +180,11 @@ unsafe extern "C" fn trampoline_new_preroll(
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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
|
gst::FlowReturn::Error
|
||||||
}
|
}
|
||||||
|
@ -208,7 +205,7 @@ unsafe extern "C" fn trampoline_new_sample(
|
||||||
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
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();
|
return gst::FlowReturn::Error.into_glib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +215,11 @@ unsafe extern "C" fn trampoline_new_sample(
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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
|
gst::FlowReturn::Error
|
||||||
}
|
}
|
||||||
|
@ -239,7 +240,7 @@ unsafe extern "C" fn trampoline_new_event(
|
||||||
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
|
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();
|
return false.into_glib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +250,11 @@ unsafe extern "C" fn trampoline_new_event(
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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
|
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(
|
unsafe extern "C" fn trampoline_need_data(
|
||||||
appsrc: *mut ffi::GstAppSrc,
|
appsrc: *mut ffi::GstAppSrc,
|
||||||
length: u32,
|
length: u32,
|
||||||
|
@ -136,7 +125,7 @@ unsafe extern "C" fn trampoline_need_data(
|
||||||
|
|
||||||
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +135,11 @@ unsafe extern "C" fn trampoline_need_data(
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +161,11 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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) {
|
if (*callbacks).panicked.load(Ordering::Relaxed) {
|
||||||
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
|
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();
|
return false.into_glib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +191,11 @@ unsafe extern "C" fn trampoline_seek_data(
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
(*callbacks).panicked.store(true, Ordering::Relaxed);
|
(*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
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -667,26 +667,11 @@ impl<O: IsA<Pad>> PadExtManual for O {
|
||||||
None => panic::resume_unwind(err),
|
None => panic::resume_unwind(err),
|
||||||
};
|
};
|
||||||
|
|
||||||
let maybe_couldnt_stop = if pad.pause_task().is_err() {
|
if pad.pause_task().is_err() {
|
||||||
", could not stop task"
|
crate::error!(crate::CAT_RUST, "could not stop pad task on panic");
|
||||||
} else {
|
}
|
||||||
""
|
|
||||||
};
|
crate::subclass::post_panic_error_message(&element, pad.upcast_ref(), Some(err));
|
||||||
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(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,7 @@ impl<T: ElementImpl> ElementImplExt for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
fn panicked(&self) -> &atomic::AtomicBool {
|
fn panicked(&self) -> &atomic::AtomicBool {
|
||||||
self.instance_data::<atomic::AtomicBool>(crate::Element::static_type())
|
self.instance_data::<atomic::AtomicBool>(crate::Element::static_type())
|
||||||
.expect("instance not initialized correctly")
|
.expect("instance not initialized correctly")
|
||||||
|
|
|
@ -2,33 +2,61 @@
|
||||||
|
|
||||||
use thiserror::Error;
|
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_export]
|
||||||
macro_rules! panic_to_error(
|
macro_rules! panic_to_error(
|
||||||
($imp:expr, $ret:expr, $code:block) => {{
|
($imp:expr, $ret:expr, $code:block) => {{
|
||||||
use std::panic::{self, AssertUnwindSafe};
|
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
|
|
||||||
#[allow(clippy::unused_unit)]
|
#[allow(clippy::unused_unit)]
|
||||||
{
|
{
|
||||||
if $imp.panicked().load(Ordering::Relaxed) {
|
let panicked = $imp.panicked();
|
||||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["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
|
$ret
|
||||||
} else {
|
} else {
|
||||||
let result = panic::catch_unwind(AssertUnwindSafe(|| $code));
|
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code));
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
$imp.panicked().store(true, Ordering::Relaxed);
|
panicked.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
if let Some(cause) = err.downcast_ref::<&str>() {
|
$crate::subclass::post_panic_error_message(
|
||||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked: {}", cause]));
|
element,
|
||||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
$crate::glib::Cast::upcast_ref::<$crate::Object>(element),
|
||||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked: {}", cause]));
|
Some(err),
|
||||||
} else {
|
);
|
||||||
$imp.post_error_message($crate::error_msg!($crate::LibraryError::Failed, ["Panicked"]));
|
|
||||||
}
|
|
||||||
$ret
|
$ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ mod uri_handler;
|
||||||
pub use self::{
|
pub use self::{
|
||||||
device_provider::DeviceProviderMetadata,
|
device_provider::DeviceProviderMetadata,
|
||||||
element::ElementMetadata,
|
element::ElementMetadata,
|
||||||
error::FlowError,
|
error::{post_panic_error_message, FlowError},
|
||||||
plugin::{MAJOR_VERSION, MINOR_VERSION},
|
plugin::{MAJOR_VERSION, MINOR_VERSION},
|
||||||
task_pool::TaskPoolFunction,
|
task_pool::TaskPoolFunction,
|
||||||
};
|
};
|
||||||
|
|
|
@ -100,24 +100,23 @@ macro_rules! plugin_define(
|
||||||
|
|
||||||
#[allow(clippy::missing_safety_doc)]
|
#[allow(clippy::missing_safety_doc)]
|
||||||
unsafe extern "C" fn plugin_init_trampoline(plugin: *mut $crate::ffi::GstPlugin) -> $crate::glib::ffi::gboolean {
|
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 {
|
match panic_result {
|
||||||
Ok(register_result) => match register_result {
|
Ok(register_result) => match register_result {
|
||||||
Ok(_) => $crate::glib::ffi::GTRUE,
|
Ok(_) => $crate::glib::ffi::GTRUE,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let cat = $crate::DebugCategory::get("GST_PLUGIN_LOADING").unwrap();
|
$crate::error!($crate::CAT_PLUGIN_LOADING, "Failed to register plugin: {}", err);
|
||||||
$crate::error!(cat, "Failed to register plugin: {}", err);
|
|
||||||
$crate::glib::ffi::GFALSE
|
$crate::glib::ffi::GFALSE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let cat = $crate::DebugCategory::get("GST_PLUGIN_LOADING").unwrap();
|
let cause = err.downcast_ref::<&str>().copied()
|
||||||
if let Some(cause) = err.downcast_ref::<&str>() {
|
.or_else(|| err.downcast_ref::<String>().map(|s| s.as_str()));
|
||||||
$crate::error!(cat, "Failed to initialize plugin due to panic: {}", cause);
|
if let Some(cause) = cause {
|
||||||
} else if let Some(cause) = err.downcast_ref::<String>() {
|
$crate::error!($crate::PLUGIN_LOADING, "Failed to initialize plugin due to panic: {}", cause);
|
||||||
$crate::error!(cat, "Failed to initialize plugin due to panic: {}", cause);
|
|
||||||
} else {
|
} else {
|
||||||
$crate::error!(cat, "Failed to initialize plugin due to panic");
|
$crate::error!(cat, "Failed to initialize plugin due to panic");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue