From a7749b793358412cef4811d4f2dbf9f24e5a831a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Oct 2020 10:42:33 +0200 Subject: [PATCH] gstreamer/log: Don't provide direct access to the logged object as glib::Object It might just be constructed or might be finalized currently and it's not safe to use any APIs on it. Instead provide a small wrapper type that allows to get the underlying pointer and that implements the Display trait to print the name of the object. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/287 --- gstreamer/src/log.rs | 82 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/gstreamer/src/log.rs b/gstreamer/src/log.rs index 19ec03c39..5de36bcbd 100644 --- a/gstreamer/src/log.rs +++ b/gstreamer/src/log.rs @@ -321,7 +321,7 @@ unsafe extern "C" fn log_handler( message: *mut gst_sys::GstDebugMessage, user_data: gpointer, ) where - T: Fn(DebugCategory, DebugLevel, &str, &str, u32, Option<&glib::Object>, &DebugMessage) + T: Fn(DebugCategory, DebugLevel, &str, &str, u32, Option<&LoggedObject>, &DebugMessage) + Send + Sync + 'static, @@ -331,7 +331,7 @@ unsafe extern "C" fn log_handler( let file = CStr::from_ptr(file).to_string_lossy(); let function = CStr::from_ptr(function).to_string_lossy(); let line = line as u32; - let object: Borrowed> = from_glib_borrow(object); + let object = ptr::NonNull::new(object).map(LoggedObject); let message = DebugMessage(ptr::NonNull::new_unchecked(message)); let handler = &*(user_data as *mut T); (handler)( @@ -340,7 +340,7 @@ unsafe extern "C" fn log_handler( &file, &function, line, - object.as_ref().as_ref(), + object.as_ref(), &message, ); } @@ -359,9 +359,81 @@ pub struct DebugLogFunction(ptr::NonNull); unsafe impl Send for DebugLogFunction {} unsafe impl Sync for DebugLogFunction {} +#[derive(Debug)] +pub struct LoggedObject(ptr::NonNull); + +impl LoggedObject { + pub fn as_ptr(&self) -> *mut gobject_sys::GObject { + self.0.as_ptr() + } +} + +impl fmt::Display for LoggedObject { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + let ptr = self.0.as_ptr(); + let g_class = (*ptr).g_type_instance.g_class; + + if !g_class.is_null() { + let type_ = (*g_class).g_type; + + if gobject_sys::g_type_is_a(type_, gst_sys::gst_pad_get_type()) != glib_sys::GFALSE + { + let name_ptr = (*(ptr as *mut gst_sys::GstObject)).name; + let name = if name_ptr.is_null() { + "" + } else { + CStr::from_ptr(name_ptr) + .to_str() + .unwrap_or("") + }; + + let parent_ptr = (*(ptr as *mut gst_sys::GstObject)).parent; + let parent_name = if parent_ptr.is_null() { + "" + } else { + let name_ptr = (*(parent_ptr as *mut gst_sys::GstObject)).name; + if name_ptr.is_null() { + "" + } else { + CStr::from_ptr(name_ptr) + .to_str() + .unwrap_or("") + } + }; + + write!(f, "{}:{}", parent_name, name) + } else if gobject_sys::g_type_is_a(type_, gst_sys::gst_object_get_type()) + != glib_sys::GFALSE + { + let name_ptr = (*(ptr as *mut gst_sys::GstObject)).name; + let name = if name_ptr.is_null() { + "" + } else { + CStr::from_ptr(name_ptr) + .to_str() + .unwrap_or("") + }; + write!(f, "{}", name) + } else { + let type_name = CStr::from_ptr(gobject_sys::g_type_name(type_)); + write!( + f, + "{}:{:?}", + type_name.to_str().unwrap_or(""), + ptr + ) + } + } else { + write!(f, "{:?}", ptr) + } + } + } +} + pub fn debug_add_log_function(function: T) -> DebugLogFunction where - T: Fn(DebugCategory, DebugLevel, &str, &str, u32, Option<&glib::Object>, &DebugMessage) + T: Fn(DebugCategory, DebugLevel, &str, &str, u32, Option<&LoggedObject>, &DebugMessage) + Send + Sync + 'static, @@ -460,7 +532,7 @@ mod tests { _file: &str, _function: &str, _line: u32, - _object: Option<&glib::Object>, + _object: Option<&LoggedObject>, message: &DebugMessage| { let cat = DebugCategory::get("test-cat-log").unwrap();