diff --git a/ChangeLog b/ChangeLog index e5ba58cb04..b94a085672 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2008-01-20 Tim-Philipp Müller + + * gst/gstplugin.c: (_gst_plugin_initialize): + Fix old-style static plugins via GST_PLUGIN_DEFINE_STATIC + again, which I broke two commits ago when changing the API + of gst_plugin_register_static(): the g_list_foreach() in + _gst_plugin_register_static still assumed the old function + signature and would therefore fail (re-fixes #510187). + + * gst/gstplugin.c: (_num_static_plugins), (_static_plugins), + (_gst_plugin_register_static), (gst_plugin_register_static): + Revert the (technically correct) change to call g_thread_init() from + the pre-main() constructor. This will break programs which call + g_thread_init() without an if (!g_thread_supported()) guard in their + main function. We could just blame it on GLib or the application, but + it's probably best to just avoid this altogether and simply not use + any GLib functions here and use plain old malloc() with a simple + array to store the plugins to register later when gst_init() is + finally called (re-fixes #510187). + + * tests/check/gst/gstplugin.c: (GST_GNUC_CONSTRUCTOR_DEFINED), + (GST_GNUC_CONSTRUCTOR_DEFINED), (plugin_init_counter), + (plugin1_init), (plugin2_init), (plugin3_init), (GST_START_TEST), + (GST_START_TEST), (gst_plugin_suite): + Dumb unit test to make sure the old GST_PLUGIN_DEFINE_STATIC still + works. + 2008-01-17 Tim-Philipp Müller * gst/gstplugin.h: (GST_PLUGIN_DEFINE_STATIC): diff --git a/common b/common index 0efbab89d3..662f544d56 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 0efbab89d333b5d07cc7da1a501c38edf5bb4f72 +Subproject commit 662f544d56a6d6ef20b8ea5f56e975f9e139bc78 diff --git a/gst/gstplugin.c b/gst/gstplugin.c index 603193cd0d..fa55cc7c4f 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -70,7 +70,8 @@ #define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING -static GList *_gst_plugin_static = NULL; +static guint _num_static_plugins; /* 0 */ +static GstPluginDesc *_static_plugins; /* NULL */ static gboolean _gst_plugin_inited; /* static variables for segfault handling of plugin loading */ @@ -169,15 +170,14 @@ _gst_plugin_register_static (GstPluginDesc * desc) g_return_if_fail (desc != NULL); if (!_gst_plugin_inited) { - /* Must call g_thread_init() before calling GLib functions such as - * g_list_prepend() ... */ - if (!g_thread_supported ()) - g_thread_init (NULL); - - if (GST_CAT_DEFAULT) - GST_LOG ("queueing static plugin \"%s\" for loading later on", - desc->name); - _gst_plugin_static = g_list_prepend (_gst_plugin_static, desc); + /* We can't use any GLib functions here, since g_thread_init hasn't been + * called yet, and we can't call it here either, or programs that don't + * guard their g_thread_init calls in main() will just abort */ + ++_num_static_plugins; + _static_plugins = + realloc (_static_plugins, _num_static_plugins * sizeof (GstPluginDesc)); + /* assume strings in the GstPluginDesc are static const or live forever */ + _static_plugins[_num_static_plugins - 1] = *desc; } else { gst_plugin_register_static (desc->major_version, desc->minor_version, desc->name, desc->description, desc->plugin_init, desc->version, @@ -252,10 +252,26 @@ gst_plugin_register_static (gint major_version, gint minor_version, void _gst_plugin_initialize (void) { + guint i; + _gst_plugin_inited = TRUE; /* now register all static plugins */ - g_list_foreach (_gst_plugin_static, (GFunc) gst_plugin_register_static, NULL); + GST_INFO ("registering %u static plugins", _num_static_plugins); + for (i = 0; i < _num_static_plugins; ++i) { + gst_plugin_register_static (_static_plugins[i].major_version, + _static_plugins[i].minor_version, _static_plugins[i].name, + _static_plugins[i].description, _static_plugins[i].plugin_init, + _static_plugins[i].version, _static_plugins[i].license, + _static_plugins[i].source, _static_plugins[i].package, + _static_plugins[i].origin); + } + + if (_static_plugins) { + free (_static_plugins); + _static_plugins = NULL; + _num_static_plugins = 0; + } } /* this function could be extended to check if the plugin license matches the diff --git a/tests/check/gst/gstplugin.c b/tests/check/gst/gstplugin.c index 62e3586685..c7463edf4d 100644 --- a/tests/check/gst/gstplugin.c +++ b/tests/check/gst/gstplugin.c @@ -29,6 +29,64 @@ void _gst_plugin_register_static (GstPluginDesc * desc); #endif +/* keep in sync with GST_GNUC_CONSTRUCTOR in gstmacros.h (ideally we'd just + * do it there, but I don't want to touch that now, and also we really want + * to deprecate this macro in the long run, I think) */ +#if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)) +#define GST_GNUC_CONSTRUCTOR_DEFINED +#else +#undef GST_GNUC_CONSTRUCTOR_DEFINED +#endif + +#ifdef GST_GNUC_CONSTRUCTOR_DEFINED +/* ------------------------------------------------------------------------- */ +/* To make sure the old and deprecated GST_PLUGIN_DEFINE_STATIC still works */ + +static guint plugin_init_counter; /* 0 */ + +static gboolean +plugin1_init (GstPlugin * plugin) +{ + ++plugin_init_counter; + return TRUE; +} + +static gboolean +plugin2_init (GstPlugin * plugin) +{ + ++plugin_init_counter; + return TRUE; +} + +static gboolean +plugin3_init (GstPlugin * plugin) +{ + ++plugin_init_counter; + return TRUE; +} + +GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "plugin-1", + "some static elements 1", plugin1_init, VERSION, GST_LICENSE, PACKAGE, + GST_PACKAGE_ORIGIN); + +GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "plugin-2", + "some static elements 2", plugin2_init, VERSION, GST_LICENSE, PACKAGE, + GST_PACKAGE_ORIGIN); + +GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "plugin-3", + "some static elements 3", plugin3_init, VERSION, GST_LICENSE, PACKAGE, + GST_PACKAGE_ORIGIN); + +GST_START_TEST (test_old_register_static) +{ + fail_unless (plugin_init_counter == 3); +} + +GST_END_TEST; + +#endif /* GST_GNUC_CONSTRUCTOR_DEFINED */ + + static gboolean register_check_elements (GstPlugin * plugin) { @@ -308,6 +366,9 @@ gst_plugin_suite (void) tcase_set_timeout (tc_chain, 60); suite_add_tcase (s, tc_chain); +#ifdef GST_GNUC_CONSTRUCTOR_DEFINED + tcase_add_test (tc_chain, test_old_register_static); +#endif tcase_add_test (tc_chain, test_register_static); tcase_add_test (tc_chain, test_registry); tcase_add_test (tc_chain, test_load_coreelements);