[gstreamer-bugs] [Bug 330598] New: [PATCH] crash in playbin and fix

GStreamer (bugzilla.gnome.org) bugzilla-daemon at bugzilla.gnome.org
Thu Feb 9 15:26:23 PST 2006


Do not reply to this via email (we are currently unable to handle email
responses and they get discarded).  You can add comments to this bug at
http://bugzilla.gnome.org/show_bug.cgi?id=330598
 GStreamer | gst-plugins-base | Ver: 0.10.2

           Summary: [PATCH] crash in playbin and fix
           Product: GStreamer
           Version: 0.10.2
          Platform: Other
        OS/Version: Linux
            Status: UNCONFIRMED
          Severity: normal
          Priority: Normal
         Component: gst-plugins-base
        AssignedTo: gstreamer-bugs at lists.sourceforge.net
        ReportedBy: wxprojects at comcast.net
         QAContact: gstreamer-bugs at lists.sourceforge.net
     GNOME version: Unspecified
   GNOME milestone: Unspecified


Due to a change to set elements to GST_STATE_NULL in remove_sinks of playbin a
crash can be introduced.  The frame member of playbin may be reliant upon the
xoverlay or another video element, so if that video element gets detroyed first
then when it tries to unref the frame member it could crash, and indeed does in
some instances depending on how the elements are layed out -in this case it is
because gst_ximagesink_ximage_destroy does not check ximagesink->xcontext for
NULL.

Program to reproduce crash in 10.2 (Note that I get this in anther actually
well-written application :)):
-----------
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>

#define TIMEOUT 100 * GST_MSECOND

GstXOverlay *x_overlay;

GtkWindow *window;
GtkWidget *videoarea;

Drawable xwindow_id;

static gboolean crashtime (GstElement * playbin)
{
    gtk_main_quit();
    return FALSE;
}

GstBusSyncReply sync_callback(GstBus *bus, GstMessage *message, 
                              gpointer)
{       
        if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) 
                return GST_BUS_PASS; 

        if (gst_structure_has_name (gst_message_get_structure(message), 
                                "prepare-xwindow-id")) 
        {
                    gst_x_overlay_set_xwindow_id(
GST_X_OVERLAY(GST_MESSAGE_SRC(message)),
                                xwindow_id)
                                ;    
                return GST_BUS_PASS;
        }

        return GST_BUS_DROP;
}

int main(int argc, char* argv[])
{
    gtk_init (&argc, &argv);
        g_thread_init(NULL);
        gdk_threads_init();
    gst_init(&argc, &argv);

    if(argc > 1)
    {
        GtkWindow*    window = (GtkWindow*)gtk_window_new
(GTK_WINDOW_TOPLEVEL);
        videoarea = gtk_drawing_area_new (); 
        gtk_widget_set_size_request(videoarea, 320, 200);

        GdkColor color;
        gdk_color_parse ("black", &color);
        gtk_widget_modify_bg (videoarea, GTK_STATE_NORMAL, &color);
        gtk_container_add (GTK_CONTAINER (window), videoarea);       
        gtk_widget_show (videoarea);
        gtk_widget_show ((GtkWidget*)window);
        gtk_widget_set_double_buffered((GtkWidget*)window, FALSE);
        Display *display;

        display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
        xwindow_id = GDK_DRAWABLE_XID((videoarea->window));

        GstElement* playbin = 
            gst_element_factory_make ("playbin", "play");

        gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (playbin)),
(GstBusSyncHandler)sync_callback, NULL);

        GstElement* videosink = 
            gst_element_factory_make("ximagesink", "video-sink");
        GstElement* audiosink = 
            gst_element_factory_make ("gconfaudiosink", "audio-sink");

    if( GST_IS_BIN(videosink) )
        x_overlay = (GstXOverlay*) 
                        gst_bin_get_by_interface (GST_BIN (videosink),
                                                  GST_TYPE_X_OVERLAY);
    else
        x_overlay = (GstXOverlay*) videosink;

        g_object_set (G_OBJECT (playbin), 
                  "video-sink", videosink,
                  "audio-sink", audiosink,
                   NULL);

        gst_element_set_state(playbin, 
                               GST_STATE_READY);
        gst_element_get_state(playbin, NULL, NULL, TIMEOUT);

        GstElement* vis = 
            gst_element_factory_make ("goom", "vis");
        g_object_set(playbin, "vis-plugin", vis, NULL);

        g_object_set (G_OBJECT (playbin), "uri", 
    argv[1], NULL);

        gst_element_set_state(playbin, 
                               GST_STATE_PAUSED);
        gst_element_get_state(playbin, NULL, NULL, TIMEOUT);

        gst_element_set_state(playbin, 
                               GST_STATE_PLAYING);
        gst_element_get_state(playbin, NULL, NULL, TIMEOUT);

        g_timeout_add (10000, (GSourceFunc) crashtime, playbin);
        gtk_main ();

        gst_element_set_state(playbin, 
                               GST_STATE_READY); /* will crash here */
        gst_element_get_state(playbin, NULL, NULL, TIMEOUT);
    }
    return 0;
}

---------
Backtrace:
---------
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1221330272 (LWP 18841)]
0xb7f30a35 in gst_ximage_buffer_finalize (ximage=0x8263b88) at ximagesink.c:491
491       if (ximagesink->xcontext->use_xshm) {
Current language:  auto; currently c
(gdb) bt
#0  0xb7f30a35 in gst_ximage_buffer_finalize (ximage=0x8263b88)
    at ximagesink.c:491
#1  0xb7e24ad9 in gst_mini_object_unref (mini_object=0x8263b88)
    at gstminiobject.c:264
#2  0xb71a75b1 in remove_sinks (play_bin=0x80f9bc8) at gstplaybin.c:764
#3  0xb71a8311 in gst_play_bin_change_state (element=0x80f9bc8,
    transition=GST_STATE_CHANGE_PAUSED_TO_READY) at gstplaybin.c:1055
#4  0xb7e17f4e in gst_element_change_state (element=0x80f9bc8,
transition=Variable "transition" is not available.
)
    at gstelement.c:2151
#5  0xb7e1805b in gst_element_change_state (element=0x80f9bc8,
transition=Variable "transition" is not available.
)
    at gstelement.c:2184
#6  0xb7e185aa in gst_element_set_state_func (element=0x80f9bc8,
    state=GST_STATE_READY) at gstelement.c:2113
#7  0xb7e1727e in gst_element_set_state (element=0x80f9bc8,
    state=GST_STATE_READY) at gstelement.c:2030
#8  0x080496aa in main (argc=2, argv=0xbfc49b34)
    at junk.cpp:109
--------------
There are several solutions of which:
1) Make playbin unref the frame member before the sinks - 
--- gst/playback/gstplaybinole.c 2006-02-09 11:15:12.000000000 -0800
+++ gst/playback/gstplaybin.c 2006-02-09 11:19:19.000000000 -0800
@@ -690,4 +690,12 @@

   GST_DEBUG ("removesinks");
+
+  /* we need to dispose of the frame before the video
+   * sink as it may be a component of it */
+  if (play_bin->frame) {
+    gst_buffer_unref (play_bin->frame);
+    play_bin->frame = NULL;
+  }
+
   element = g_hash_table_lookup (play_bin->cache, "abin");
   if (element != NULL) {
@@ -761,9 +769,4 @@
   }

-  if (play_bin->frame) {
-    gst_buffer_unref (play_bin->frame);
-    play_bin->frame = NULL;
-  }
-
   play_bin->textoverlay_element = NULL;
}

-----------
2) Change ximagesink to check for NULL for ximagesink->xcontext in
gst_ximagesink_ximage_destroy
--- sys/ximage/ximagesinkole.c 2006-01-16 07:28:47.000000000 -0800
+++ sys/ximage/ximagesink.c 2006-02-09 11:32:47.000000000 -0800
@@ -489,5 +489,5 @@

#ifdef HAVE_XSHM
-  if (ximagesink->xcontext->use_xshm) {
+  if (ximagesink->xcontext && ximagesink->xcontext->use_xshm) {
     if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
       XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo);
@@ -508,5 +508,7 @@
   }

+  if(ximagesink->xcontext) {
   XSync (ximagesink->xcontext->disp, FALSE);
+  }

   g_mutex_unlock (ximagesink->x_lock);

-----------
3) Or, if this is desired behaviour perhaps a simple 

g_return_if_fail (ximagesink->xcontext != NULL);

or similar could be added to the top of gst_ximagesink_ximage_destroy


-- 
Configure bugmail: http://bugzilla.gnome.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.




More information about the Gstreamer-bugs mailing list