mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-25 11:01:10 +00:00
pad: Catch panics in pad task functions
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/246
This commit is contained in:
parent
49faa03c98
commit
8d3ada5d89
1 changed files with 51 additions and 16 deletions
|
@ -1,8 +1,10 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use crate::element::ElementExtManual;
|
||||
use crate::format::{
|
||||
FormattedValue, SpecificFormattedValueFullRange, SpecificFormattedValueIntrinsic,
|
||||
};
|
||||
use crate::prelude::PadExt;
|
||||
use crate::Buffer;
|
||||
use crate::BufferList;
|
||||
use crate::Event;
|
||||
|
@ -22,6 +24,7 @@ use crate::{Format, GenericFormattedValue};
|
|||
use std::mem;
|
||||
use std::num::NonZeroU64;
|
||||
use std::ops::ControlFlow;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::ptr;
|
||||
|
||||
use glib::ffi::gpointer;
|
||||
|
@ -709,12 +712,59 @@ impl<O: IsA<Pad>> PadExtManual for O {
|
|||
}
|
||||
|
||||
fn start_task<F: FnMut() + Send + 'static>(&self, func: F) -> Result<(), glib::BoolError> {
|
||||
unsafe extern "C" fn trampoline_pad_task<F: FnMut() + Send + 'static>(func: gpointer) {
|
||||
let (func, pad) = &mut *(func as *mut (F, *mut ffi::GstPad));
|
||||
let pad = Pad::from_glib_borrow(*pad);
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(func));
|
||||
|
||||
if let Err(err) = result {
|
||||
let element = match pad.parent_element() {
|
||||
Some(element) => element,
|
||||
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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn into_raw_pad_task<F: FnMut() + Send + 'static>(
|
||||
func: F,
|
||||
pad: *mut ffi::GstPad,
|
||||
) -> gpointer {
|
||||
#[allow(clippy::type_complexity)]
|
||||
let func: Box<(F, *mut ffi::GstPad)> = Box::new((func, pad));
|
||||
Box::into_raw(func) as gpointer
|
||||
}
|
||||
|
||||
unsafe extern "C" fn destroy_closure_pad_task<F>(ptr: gpointer) {
|
||||
let _ = Box::<(F, *mut ffi::GstPad)>::from_raw(ptr as *mut _);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
glib::result_from_gboolean!(
|
||||
ffi::gst_pad_start_task(
|
||||
self.as_ref().to_glib_none().0,
|
||||
Some(trampoline_pad_task::<F>),
|
||||
into_raw_pad_task(func),
|
||||
into_raw_pad_task(func, self.upcast_ref().as_ptr()),
|
||||
Some(destroy_closure_pad_task::<F>),
|
||||
),
|
||||
"Failed to start pad task",
|
||||
|
@ -1536,21 +1586,6 @@ unsafe extern "C" fn destroy_closure<F>(ptr: gpointer) {
|
|||
let _ = Box::<F>::from_raw(ptr as *mut _);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn trampoline_pad_task<F: FnMut() + Send + 'static>(func: gpointer) {
|
||||
let func: &mut F = &mut *(func as *mut F);
|
||||
func()
|
||||
}
|
||||
|
||||
fn into_raw_pad_task<F: FnMut() + Send + 'static>(func: F) -> gpointer {
|
||||
#[allow(clippy::type_complexity)]
|
||||
let func: Box<F> = Box::new(func);
|
||||
Box::into_raw(func) as gpointer
|
||||
}
|
||||
|
||||
unsafe extern "C" fn destroy_closure_pad_task<F>(ptr: gpointer) {
|
||||
let _ = Box::<F>::from_raw(ptr as *mut _);
|
||||
}
|
||||
|
||||
impl Pad {
|
||||
#[doc(alias = "gst_pad_new")]
|
||||
pub fn new(name: Option<&str>, direction: crate::PadDirection) -> Self {
|
||||
|
|
Loading…
Reference in a new issue