Improve code generation with panic=abort around panic handling code

None of that can ever be called in that case but the compiler can't know
that in more complicated cases like these. Handling it explicitly allows
no handling code to be generated at all here, like would already happen
everywhere else.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1441>
This commit is contained in:
Sebastian Dröge 2024-05-16 16:38:15 +03:00
parent 0ef80c4fe7
commit b468280353
4 changed files with 156 additions and 65 deletions

View file

@ -4,13 +4,13 @@ use std::{
mem, panic, mem, panic,
pin::Pin, pin::Pin,
ptr, ptr,
sync::{ sync::{Arc, Mutex},
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
task::{Context, Poll, Waker}, task::{Context, Poll, Waker},
}; };
#[cfg(not(panic = "abort"))]
use std::sync::atomic::{AtomicBool, Ordering};
use futures_core::Stream; use futures_core::Stream;
use glib::{ffi::gpointer, prelude::*, translate::*}; use glib::{ffi::gpointer, prelude::*, translate::*};
@ -28,6 +28,7 @@ pub struct AppSinkCallbacks {
new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>, new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
propose_allocation: propose_allocation:
Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>, Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
#[cfg(not(panic = "abort"))]
panicked: AtomicBool, panicked: AtomicBool,
callbacks: ffi::GstAppSinkCallbacks, callbacks: ffi::GstAppSinkCallbacks,
} }
@ -194,6 +195,7 @@ impl AppSinkCallbacksBuilder {
new_sample: self.new_sample, new_sample: self.new_sample,
new_event: self.new_event, new_event: self.new_event,
propose_allocation: self.propose_allocation, propose_allocation: self.propose_allocation,
#[cfg(not(panic = "abort"))]
panicked: AtomicBool::new(false), panicked: AtomicBool::new(false),
callbacks: ffi::GstAppSinkCallbacks { callbacks: ffi::GstAppSinkCallbacks {
eos: if have_eos { Some(trampoline_eos) } else { None }, eos: if have_eos { Some(trampoline_eos) } else { None },
@ -227,6 +229,7 @@ unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gp
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);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -238,12 +241,19 @@ unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gp
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
}
} }
} }
} }
@ -256,6 +266,7 @@ unsafe extern "C" fn trampoline_new_preroll(
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);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -267,14 +278,21 @@ unsafe extern "C" fn trampoline_new_preroll(
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
gst::FlowReturn::Error gst::FlowReturn::Error
}
} }
} }
} else { } else {
@ -291,6 +309,7 @@ unsafe extern "C" fn trampoline_new_sample(
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);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -302,14 +321,21 @@ unsafe extern "C" fn trampoline_new_sample(
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
gst::FlowReturn::Error gst::FlowReturn::Error
}
} }
} }
} else { } else {
@ -326,6 +352,7 @@ unsafe extern "C" fn trampoline_new_event(
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);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -337,14 +364,21 @@ unsafe extern "C" fn trampoline_new_event(
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
false false
}
} }
} }
} else { } else {
@ -362,6 +396,7 @@ unsafe extern "C" fn trampoline_propose_allocation(
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);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -379,14 +414,20 @@ unsafe extern "C" fn trampoline_propose_allocation(
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
false gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
false
}
} }
} }
} else { } else {

View file

@ -4,13 +4,13 @@ use std::{
mem, panic, mem, panic,
pin::Pin, pin::Pin,
ptr, ptr,
sync::{ sync::{Arc, Mutex},
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
task::{Context, Poll, Waker}, task::{Context, Poll, Waker},
}; };
#[cfg(not(panic = "abort"))]
use std::sync::atomic::{AtomicBool, Ordering};
use futures_sink::Sink; use futures_sink::Sink;
use glib::{ use glib::{
ffi::{gboolean, gpointer}, ffi::{gboolean, gpointer},
@ -25,6 +25,7 @@ pub struct AppSrcCallbacks {
need_data: Option<Box<dyn FnMut(&AppSrc, u32) + Send + 'static>>, need_data: Option<Box<dyn FnMut(&AppSrc, u32) + Send + 'static>>,
enough_data: Option<Box<dyn Fn(&AppSrc) + Send + Sync + 'static>>, enough_data: Option<Box<dyn Fn(&AppSrc) + Send + Sync + 'static>>,
seek_data: Option<Box<dyn Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>>, seek_data: Option<Box<dyn Fn(&AppSrc, u64) -> bool + Send + Sync + 'static>>,
#[cfg(not(panic = "abort"))]
panicked: AtomicBool, panicked: AtomicBool,
callbacks: ffi::GstAppSrcCallbacks, callbacks: ffi::GstAppSrcCallbacks,
} }
@ -120,6 +121,7 @@ impl AppSrcCallbacksBuilder {
need_data: self.need_data, need_data: self.need_data,
enough_data: self.enough_data, enough_data: self.enough_data,
seek_data: self.seek_data, seek_data: self.seek_data,
#[cfg(not(panic = "abort"))]
panicked: AtomicBool::new(false), panicked: AtomicBool::new(false),
callbacks: ffi::GstAppSrcCallbacks { callbacks: ffi::GstAppSrcCallbacks {
need_data: if have_need_data { need_data: if have_need_data {
@ -156,6 +158,7 @@ unsafe extern "C" fn trampoline_need_data(
let callbacks = callbacks as *mut AppSrcCallbacks; let callbacks = callbacks as *mut AppSrcCallbacks;
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc); let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -167,12 +170,19 @@ unsafe extern "C" fn trampoline_need_data(
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
}
} }
} }
} }
@ -182,6 +192,7 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
let callbacks = callbacks as *const AppSrcCallbacks; let callbacks = callbacks as *const AppSrcCallbacks;
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc); let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -193,12 +204,19 @@ unsafe extern "C" fn trampoline_enough_data(appsrc: *mut ffi::GstAppSrc, callbac
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
}
} }
} }
} }
@ -212,6 +230,7 @@ unsafe extern "C" fn trampoline_seek_data(
let callbacks = callbacks as *const AppSrcCallbacks; let callbacks = callbacks as *const AppSrcCallbacks;
let element: Borrowed<AppSrc> = from_glib_borrow(appsrc); let element: Borrowed<AppSrc> = from_glib_borrow(appsrc);
#[cfg(not(panic = "abort"))]
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::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None); gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
@ -223,14 +242,21 @@ unsafe extern "C" fn trampoline_seek_data(
match result { match result {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed); #[cfg(panic = "abort")]
gst::subclass::post_panic_error_message( {
element.upcast_ref(), unreachable!("{err:?}");
element.upcast_ref(), }
Some(err), #[cfg(not(panic = "abort"))]
); {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
false false
}
} }
} }
} else { } else {

View file

@ -286,8 +286,16 @@ pub trait ElementImplExt: sealed::Sealed + ObjectSubclass {
#[inline(never)] #[inline(never)]
fn panicked(&self) -> &atomic::AtomicBool { fn panicked(&self) -> &atomic::AtomicBool {
self.instance_data::<atomic::AtomicBool>(crate::Element::static_type()) #[cfg(panic = "abort")]
.expect("instance not initialized correctly") {
static DUMMY: atomic::AtomicBool = atomic::AtomicBool::new(false);
&DUMMY
}
#[cfg(not(panic = "abort"))]
{
self.instance_data::<atomic::AtomicBool>(crate::Element::static_type())
.expect("instance not initialized correctly")
}
} }
fn catch_panic<R, F: FnOnce(&Self) -> R, G: FnOnce() -> R>(&self, fallback: G, f: F) -> R { fn catch_panic<R, F: FnOnce(&Self) -> R, G: FnOnce() -> R>(&self, fallback: G, f: F) -> R {
@ -408,6 +416,7 @@ unsafe impl<T: ElementImpl> IsSubclassable<T> for Element {
fn instance_init(instance: &mut glib::subclass::InitializingObject<T>) { fn instance_init(instance: &mut glib::subclass::InitializingObject<T>) {
Self::parent_instance_init::<T>(instance); Self::parent_instance_init::<T>(instance);
#[cfg(not(panic = "abort"))]
instance.set_instance_data(Self::static_type(), atomic::AtomicBool::new(false)); instance.set_instance_data(Self::static_type(), atomic::AtomicBool::new(false));
} }
} }
@ -429,7 +438,10 @@ unsafe extern "C" fn element_change_state<T: ElementImpl>(
_ => StateChangeReturn::Failure, _ => StateChangeReturn::Failure,
}; };
panic_to_error!(imp, fallback, { imp.change_state(transition).into() }).into_glib() panic_to_error!(imp, fallback, {
StateChangeReturn::from(imp.change_state(transition))
})
.into_glib()
} }
unsafe extern "C" fn element_request_new_pad<T: ElementImpl>( unsafe extern "C" fn element_request_new_pad<T: ElementImpl>(

View file

@ -34,6 +34,18 @@ pub fn post_panic_error_message(
macro_rules! panic_to_error( macro_rules! panic_to_error(
($imp:expr, $ret:expr, $code:block) => {{ ($imp:expr, $ret:expr, $code:block) => {{
#[allow(clippy::unused_unit)] #[allow(clippy::unused_unit)]
#[cfg(panic = "abort")]
{
if true {
#[allow(unused_mut)]
let mut closure = || { $code };
closure()
} else {
let _imp = $imp;
$ret
}
}
#[cfg(not(panic = "abort"))]
{ {
let panicked = $imp.panicked(); let panicked = $imp.panicked();
let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp); let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);