Fix unsafety of pad probes and sync bus handler

These can't be FnMut but must be Fn as they can be called from many
threads at the same time.
This commit is contained in:
Sebastian Dröge 2017-08-01 15:28:36 +01:00
parent 7b98b2e7da
commit 7c600bfce3
2 changed files with 41 additions and 26 deletions

View file

@ -46,18 +46,18 @@ unsafe extern "C" fn trampoline_sync(
func: gpointer, func: gpointer,
) -> ffi::GstBusSyncReply { ) -> ffi::GstBusSyncReply {
let _guard = CallbackGuard::new(); let _guard = CallbackGuard::new();
let func: &RefCell<Box<FnMut(&Bus, &Message) -> BusSyncReply + 'static>> = transmute(func); let f: &Box<Fn(&Bus, &Message) -> BusSyncReply + 'static> = transmute(func);
(&mut *func.borrow_mut())(&from_glib_none(bus), &Message::from_glib_none(msg)).to_glib() f(&from_glib_none(bus), &Message::from_glib_none(msg)).to_glib()
} }
unsafe extern "C" fn destroy_closure_sync(ptr: gpointer) { unsafe extern "C" fn destroy_closure_sync(ptr: gpointer) {
let _guard = CallbackGuard::new(); let _guard = CallbackGuard::new();
Box::<RefCell<Box<FnMut(&Bus, &Message) -> BusSyncReply + 'static>>>::from_raw(ptr as *mut _); Box::<Box<Fn(&Bus, &Message) -> BusSyncReply + 'static>>::from_raw(ptr as *mut _);
} }
fn into_raw_sync<F: FnMut(&Bus, &Message) -> BusSyncReply + Send + 'static>(func: F) -> gpointer { fn into_raw_sync<F: Fn(&Bus, &Message) -> BusSyncReply + Send + 'static>(func: F) -> gpointer {
let func: Box<RefCell<Box<FnMut(&Bus, &Message) -> BusSyncReply + Send + 'static>>> = let func: Box<Box<Fn(&Bus, &Message) -> BusSyncReply + Send + 'static>> =
Box::new(RefCell::new(Box::new(func))); Box::new(Box::new(func));
Box::into_raw(func) as gpointer Box::into_raw(func) as gpointer
} }
@ -108,7 +108,7 @@ impl Bus {
pub fn set_sync_handler<F>(&self, func: F) pub fn set_sync_handler<F>(&self, func: F)
where where
F: FnMut(&Bus, &Message) -> BusSyncReply + Send + 'static, F: Fn(&Bus, &Message) -> BusSyncReply + Send + Sync + 'static,
{ {
unsafe { unsafe {
ffi::gst_bus_set_sync_handler( ffi::gst_bus_set_sync_handler(

View file

@ -17,7 +17,6 @@ use QueryRef;
use Event; use Event;
use miniobject::MiniObject; use miniobject::MiniObject;
use std::cell::RefCell;
use std::mem::transmute; use std::mem::transmute;
use std::ptr; use std::ptr;
@ -68,7 +67,7 @@ pub enum PadProbeData<'a> {
pub trait PadExtManual { pub trait PadExtManual {
fn add_probe<F>(&self, mask: PadProbeType, func: F) -> PadProbeId fn add_probe<F>(&self, mask: PadProbeType, func: F) -> PadProbeId
where where
F: FnMut(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static; F: Fn(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static;
fn remove_probe(&self, id: PadProbeId); fn remove_probe(&self, id: PadProbeId);
fn chain(&self, buffer: Buffer) -> FlowReturn; fn chain(&self, buffer: Buffer) -> FlowReturn;
@ -87,7 +86,11 @@ pub trait PadExtManual {
fn proxy_query_caps(&self, query: &mut QueryRef) -> bool; fn proxy_query_caps(&self, query: &mut QueryRef) -> bool;
fn proxy_query_accept_caps(&self, query: &mut QueryRef) -> bool; fn proxy_query_accept_caps(&self, query: &mut QueryRef) -> bool;
fn event_default<'a, P: IsA<::Object> + 'a, Q: Into<Option<&'a P>>>(&self, parent: Q, event: Event) -> bool; fn event_default<'a, P: IsA<::Object> + 'a, Q: Into<Option<&'a P>>>(
&self,
parent: Q,
event: Event,
) -> bool;
fn push_event(&self, event: Event) -> bool; fn push_event(&self, event: Event) -> bool;
fn send_event(&self, event: Event) -> bool; fn send_event(&self, event: Event) -> bool;
} }
@ -95,7 +98,7 @@ pub trait PadExtManual {
impl<O: IsA<Pad>> PadExtManual for O { impl<O: IsA<Pad>> PadExtManual for O {
fn add_probe<F>(&self, mask: PadProbeType, func: F) -> PadProbeId fn add_probe<F>(&self, mask: PadProbeType, func: F) -> PadProbeId
where where
F: FnMut(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static, F: Fn(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static,
{ {
unsafe { unsafe {
let id = ffi::gst_pad_add_probe( let id = ffi::gst_pad_add_probe(
@ -210,23 +213,37 @@ impl<O: IsA<Pad>> PadExtManual for O {
} }
} }
fn event_default<'a, P: IsA<::Object> + 'a, Q: Into<Option<&'a P>>>(&self, parent: Q, event: Event) -> bool { fn event_default<'a, P: IsA<::Object> + 'a, Q: Into<Option<&'a P>>>(
&self,
parent: Q,
event: Event,
) -> bool {
let parent = parent.into(); let parent = parent.into();
let parent = parent.to_glib_none(); let parent = parent.to_glib_none();
unsafe { unsafe {
from_glib(ffi::gst_pad_event_default(self.to_glib_none().0, parent.0, event.into_ptr())) from_glib(ffi::gst_pad_event_default(
self.to_glib_none().0,
parent.0,
event.into_ptr(),
))
} }
} }
fn push_event(&self, event: Event) -> bool { fn push_event(&self, event: Event) -> bool {
unsafe { unsafe {
from_glib(ffi::gst_pad_push_event(self.to_glib_none().0, event.into_ptr())) from_glib(ffi::gst_pad_push_event(
self.to_glib_none().0,
event.into_ptr(),
))
} }
} }
fn send_event(&self, event: Event) -> bool { fn send_event(&self, event: Event) -> bool {
unsafe { unsafe {
from_glib(ffi::gst_pad_send_event(self.to_glib_none().0, event.into_ptr())) from_glib(ffi::gst_pad_send_event(
self.to_glib_none().0,
event.into_ptr(),
))
} }
} }
} }
@ -237,9 +254,8 @@ unsafe extern "C" fn trampoline_pad_probe(
func: gpointer, func: gpointer,
) -> ffi::GstPadProbeReturn { ) -> ffi::GstPadProbeReturn {
let _guard = CallbackGuard::new(); let _guard = CallbackGuard::new();
let func: &RefCell< let func: &Box<Fn(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static> =
Box<FnMut(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static>, transmute(func);
> = transmute(func);
let mut data_type = None; let mut data_type = None;
let mut probe_info = PadProbeInfo { let mut probe_info = PadProbeInfo {
@ -277,7 +293,7 @@ unsafe extern "C" fn trampoline_pad_probe(
}, },
}; };
let ret = (&mut *func.borrow_mut())(&from_glib_none(pad), &mut probe_info).to_glib(); let ret = func(&from_glib_none(pad), &mut probe_info).to_glib();
match probe_info.data { match probe_info.data {
Some(PadProbeData::Buffer(buffer)) => { Some(PadProbeData::Buffer(buffer)) => {
@ -316,16 +332,15 @@ unsafe extern "C" fn trampoline_pad_probe(
unsafe extern "C" fn destroy_closure_pad_probe(ptr: gpointer) { unsafe extern "C" fn destroy_closure_pad_probe(ptr: gpointer) {
let _guard = CallbackGuard::new(); let _guard = CallbackGuard::new();
Box::<RefCell<Box<FnMut(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static>>>::from_raw(ptr as *mut _); Box::<Box<Fn(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static>>::from_raw(
ptr as *mut _,
);
} }
fn into_raw_pad_probe< fn into_raw_pad_probe<F: Fn(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static>(
F: FnMut(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static,
>(
func: F, func: F,
) -> gpointer { ) -> gpointer {
let func: Box< let func: Box<Box<Fn(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static>> =
RefCell<Box<FnMut(&Pad, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static>>, Box::new(Box::new(func));
> = Box::new(RefCell::new(Box::new(func)));
Box::into_raw(func) as gpointer Box::into_raw(func) as gpointer
} }