diff --git a/ChangeLog b/ChangeLog index 63061c039c..5a97bd33fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2007-01-05 Tim-Philipp Müller + + * gst/gst.c: (gst_init_get_option_group), (gst_init_check), + (init_pre): + Call g_thread_init() first thing in gst_init() / gst_check_init(). + When initialisation is done via gst_init_get_option_group() and + GOption parsing, issue a warning if the GLib thread system has not + been initialised yet by the time gst_init_get_option_group() is + called, as it's quite likely other GLib functions such as + g_option_context_new() have been called already then, and + g_thread_init() must be called before any other GLib function. The + application in question must be fixed in that case, since memory + corruption might happen otherwise. + We issue the warning because even if the GLib folks decide to work + around the problem on their end in future, this is still an issue + with all GLib versions >= 2.10.0, so we should warn until we depend + on a GLib version we know to be safe. + Update documentation as well. + Closes bug #391278. + 2007-01-05 Tim-Philipp Müller * tools/gst-inspect.c: (main): diff --git a/gst/gst.c b/gst/gst.c index 6ad290a3ea..77c42f5c01 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -76,7 +76,10 @@ * N_("Output tags (also known as metadata)"), NULL}, * {NULL} * }; - * ctx = g_option_context_new ("gst-launch"); + * // must initialise the threading system before using any other GLib funtion + * if (!g_thread_supported ()) + * g_thread_init (NULL); + * ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]"); * g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); * g_option_context_add_group (ctx, gst_init_get_option_group ()); * if (!g_option_context_parse (ctx, &argc, &argv, &err)) { @@ -279,8 +282,11 @@ parse_debug_list (const gchar * list) * This function is useful if you want to integrate GStreamer with other * libraries that use GOption (see g_option_context_add_group() ). * - * Returns: a pointer to GStreamer's option group. Should be dereferenced - * after use. + * If you use this function, you should make sure you initialise the GLib + * threading system as one of the very first things in your program + * (see the example at the beginning of this section). + * + * Returns: a pointer to GStreamer's option group. */ GOptionGroup * @@ -337,6 +343,20 @@ gst_init_get_option_group (void) {NULL} }; + /* The GLib threading system must be initialised before calling any other + * GLib function according to the documentation; if the application hasn't + * called gst_init() yet or initialised the threading system otherwise, we + * better issue a warning here (since chances are high that the application + * has already called other GLib functions such as g_option_context_new() */ + if (!g_thread_supported ()) { + g_warning ("The GStreamer function gst_init_get_option_group() was\n" + "\tcalled, but the GLib threading system has not been initialised\n" + "\tyet, something that must happen before any other GLib function\n" + "\tis called. The application needs to be fixed accordingly, please\n" + "\tfile a bug against this application."); + g_thread_init (NULL); + } + group = g_option_group_new ("gst", _("GStreamer Options"), _("Show GStreamer Options"), NULL, NULL); g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre, @@ -361,6 +381,10 @@ gst_init_get_option_group (void) * for some reason. If you want your program to fail fatally, * use gst_init() instead. * + * This function should be called before calling any other GLib functions. If + * this is not an option, your program must initialise the GLib thread system + * using g_thread_init() before any other GLib functions are called. + * * Returns: %TRUE if GStreamer could be initialized. */ gboolean @@ -370,6 +394,9 @@ gst_init_check (int *argc, char **argv[], GError ** err) GOptionContext *ctx; gboolean res; + if (!g_thread_supported ()) + g_thread_init (NULL); + GST_INFO ("initializing GStreamer"); if (gst_initialized) { @@ -403,6 +430,10 @@ gst_init_check (int *argc, char **argv[], GError ** err) * Initializes the GStreamer library, setting up internal path lists, * registering built-in elements, and loading standard plugins. * + * This function should be called before calling any other GLib functions. If + * this is not an option, your program must initialise the GLib thread system + * using g_thread_init() before any other GLib functions are called. + * * * This function will terminate your program if it was unable to initialize * GStreamer for some reason. If you want your program to fall back, @@ -519,12 +550,8 @@ init_pre (GOptionContext * context, GOptionGroup * group, gpointer data, g_type_init (); - if (g_thread_supported ()) { - /* somebody already initialized threading */ - } else { - g_thread_init (NULL); - } /* we need threading to be enabled right here */ + g_assert (g_thread_supported ()); _gst_debug_init (); #ifdef ENABLE_NLS