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

View file

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

View file

@ -286,9 +286,17 @@ pub trait ElementImplExt: sealed::Sealed + ObjectSubclass {
#[inline(never)]
fn panicked(&self) -> &atomic::AtomicBool {
#[cfg(panic = "abort")]
{
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 {
panic_to_error!(self, fallback(), { f(self) })
@ -408,6 +416,7 @@ unsafe impl<T: ElementImpl> IsSubclassable<T> for Element {
fn instance_init(instance: &mut glib::subclass::InitializingObject<T>) {
Self::parent_instance_init::<T>(instance);
#[cfg(not(panic = "abort"))]
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,
};
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>(

View file

@ -34,6 +34,18 @@ pub fn post_panic_error_message(
macro_rules! panic_to_error(
($imp:expr, $ret:expr, $code:block) => {{
#[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 element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);