From 0b74058fa3144f85b5fefd4c81129b971010452a Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Fri, 10 Sep 2010 16:21:37 -0400 Subject: [PATCH] Add work-around for Bug 627724 The root problem is with GObject - for now, just work around it in GDBus. Also include a test-case. See https://bugzilla.gnome.org/show_bug.cgi?id=627724 for more information. Signed-off-by: David Zeuthen --- gio/gdbusprivate.c | 44 +++++++++++++++++++++- gio/tests/Makefile.am | 4 ++ gio/tests/gdbus-bz627724.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 gio/tests/gdbus-bz627724.c diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c index ca2680b..ba4ecb1 100644 --- a/gio/gdbusprivate.c +++ b/gio/gdbusprivate.c @@ -229,6 +229,34 @@ _g_socket_read_with_control_messages_finish (GSocket *socket, /* ---------------------------------------------------------------------------------------------------- */ +/* Work-around for https://bugzilla.gnome.org/show_bug.cgi?id=627724 */ + +static GPtrArray *ensured_classes = NULL; + +static void +ensure_type (GType gtype) +{ + g_ptr_array_add (ensured_classes, g_type_class_ref (gtype)); +} + +static void +released_required_types (void) +{ + g_ptr_array_foreach (ensured_classes, (GFunc) g_type_class_unref, NULL); + g_ptr_array_unref (ensured_classes); + ensured_classes = NULL; +} + +static void +ensure_required_types (void) +{ + g_assert (ensured_classes == NULL); + ensured_classes = g_ptr_array_new (); + ensure_type (G_TYPE_SIMPLE_ASYNC_RESULT); + ensure_type (G_TYPE_MEMORY_INPUT_STREAM); +} +/* ---------------------------------------------------------------------------------------------------- */ + G_LOCK_DEFINE_STATIC (shared_thread_lock); typedef struct @@ -242,7 +270,7 @@ typedef struct static SharedThreadData *shared_thread_data = NULL; static gpointer -shared_thread_func (gpointer data) +gdbus_shared_thread_func (gpointer data) { g_main_context_push_thread_default (shared_thread_data->context); g_main_loop_run (shared_thread_data->loop); @@ -268,6 +296,8 @@ invoke_caller (gpointer user_data) return FALSE; } +/* ---------------------------------------------------------------------------------------------------- */ + static void _g_dbus_shared_thread_ref (GDBusSharedThreadFunc func, gpointer user_data) @@ -275,9 +305,12 @@ _g_dbus_shared_thread_ref (GDBusSharedThreadFunc func, GError *error; GSource *idle_source; CallerData *data; + gboolean release_types; G_LOCK (shared_thread_lock); + release_types = FALSE; + if (shared_thread_data != NULL) { shared_thread_data->num_users += 1; @@ -287,10 +320,14 @@ _g_dbus_shared_thread_ref (GDBusSharedThreadFunc func, shared_thread_data = g_new0 (SharedThreadData, 1); shared_thread_data->num_users = 1; + /* Work-around for https://bugzilla.gnome.org/show_bug.cgi?id=627724 */ + ensure_required_types (); + release_types = TRUE; + error = NULL; shared_thread_data->context = g_main_context_new (); shared_thread_data->loop = g_main_loop_new (shared_thread_data->context, FALSE); - shared_thread_data->thread = g_thread_create (shared_thread_func, + shared_thread_data->thread = g_thread_create (gdbus_shared_thread_func, NULL, TRUE, &error); @@ -316,6 +353,9 @@ _g_dbus_shared_thread_ref (GDBusSharedThreadFunc func, while (!data->done) g_thread_yield (); + if (release_types) + released_required_types (); + g_free (data); G_UNLOCK (shared_thread_lock); diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index d5d679e..8e42a90 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -57,6 +57,7 @@ TEST_PROGS += \ gdbus-peer \ gdbus-exit-on-close \ gdbus-non-socket \ + gdbus-bz627724 \ application \ testapps \ appinfo \ @@ -217,6 +218,9 @@ endif gdbus_addresses_SOURCES = gdbus-addresses.c gdbus_addresses_LDADD = $(progs_ldadd) +gdbus_bz627724_SOURCES = gdbus-bz627724.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c +gdbus_bz627724_LDADD = $(progs_ldadd) + gdbus_connection_SOURCES = gdbus-connection.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c gdbus_connection_LDADD = $(progs_ldadd) diff --git a/gio/tests/gdbus-bz627724.c b/gio/tests/gdbus-bz627724.c new file mode 100644 index 0000000..03d196e --- /dev/null +++ b/gio/tests/gdbus-bz627724.c @@ -0,0 +1,94 @@ +/* GLib testing framework examples and tests + * + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen + */ + +#include +#include +#include + +#include "gdbus-tests.h" + +static GDBusConnection *the_connection = NULL; + +#define MY_TYPE_OBJECT (my_object_get_type ()) +#define MY_OBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MY_TYPE_OBJECT, MyObject)) +#define MY_IS_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MY_TYPE_OBJECT)) + +typedef struct { + GObject parent_instance; +} MyObject; + +typedef struct { + GObjectClass parent_class; +} MyObjectClass; + +GType my_object_get_type (void) G_GNUC_CONST; + +G_DEFINE_TYPE (MyObject, my_object, G_TYPE_OBJECT); + +static void +my_object_init (MyObject *object) +{ +} + +static void +my_object_class_init (MyObjectClass *klass) +{ + GError *error; + error = NULL; + the_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, + NULL, /* GCancellable* */ + &error); + g_assert_no_error (error); + g_assert (G_IS_DBUS_CONNECTION (the_connection)); +} + +static void +test_bz627724 (void) +{ + MyObject *object; + + session_bus_up (); + g_assert (the_connection == NULL); + object = g_object_new (MY_TYPE_OBJECT, NULL); + g_assert (the_connection != NULL); + g_object_unref (the_connection); + g_object_unref (object); + session_bus_down (); +} + + +int +main (int argc, + char *argv[]) +{ + g_type_init (); + g_test_init (&argc, &argv, NULL); + + /* all the tests use a session bus with a well-known address that we can bring up and down + * using session_bus_up() and session_bus_down(). + */ + g_unsetenv ("DISPLAY"); + g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE); + + g_test_add_func ("/gdbus/bz627724", test_bz627724); + return g_test_run(); +} -- 2.7.4