plugins: Do not ever unload a plugin after calling into it
authorBenjamin Otte <otte@redhat.com>
Fri, 12 Mar 2010 15:42:47 +0000 (16:42 +0100)
committerBenjamin Otte <otte@redhat.com>
Fri, 12 Mar 2010 15:56:56 +0000 (16:56 +0100)
This is what can happen in a plugin_init function:
- An element based on GstBaseSink is registered
- Other elements fail to register
- The plugin_init function returns FALSE

Now if this the plugin is the first plugin to link against
libgstbase.so, it will have caused libgstbase.so to be loaded and static
strings from that library will have been added to gobject while
registering GstBaseSink.

So unloading the plugin will cause those strings to go stale and the
next plugin using GstBaseSink will crash. So we must not unload modules
after calling into them ever.

https://bugzilla.redhat.com/show_bug.cgi?id=572800

gst/gstplugin.c

index 0f146ae..af62434 100644 (file)
@@ -412,18 +412,22 @@ gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc,
 
   gst_plugin_desc_copy (&plugin->desc, desc);
 
+  /* make resident so we're really sure it never gets unloaded again.
+   * Theoretically this is not needed, but practically it doesn't hurt.
+   * And we're rather safe than sorry. */
+  if (plugin->module)
+    g_module_make_resident (plugin->module);
+
   if (user_data) {
     if (!(((GstPluginInitFullFunc) (desc->plugin_init)) (plugin, user_data))) {
       if (GST_CAT_DEFAULT)
         GST_WARNING ("plugin \"%s\" failed to initialise", plugin->filename);
-      plugin->module = NULL;
       return NULL;
     }
   } else {
     if (!((desc->plugin_init) (plugin))) {
       if (GST_CAT_DEFAULT)
         GST_WARNING ("plugin \"%s\" failed to initialise", plugin->filename);
-      plugin->module = NULL;
       return NULL;
     }
   }
@@ -646,7 +650,6 @@ gst_plugin_load_file (const gchar * filename, GError ** error)
         GST_PLUGIN_ERROR_MODULE,
         "File \"%s\" appears to be a GStreamer plugin, but it failed to initialize",
         filename);
-    g_module_close (module);
     goto return_error;
   }