diff --git a/gio/gactiongroupexporter.c b/gio/gactiongroupexporter.c index 136928cb7..ef8f18a65 100644 --- a/gio/gactiongroupexporter.c +++ b/gio/gactiongroupexporter.c @@ -216,6 +216,7 @@ typedef struct { GActionGroup *action_group; GDBusConnection *connection; + GMainContext *context; gchar *object_path; GHashTable *pending_changes; GSource *pending_source; @@ -329,7 +330,7 @@ g_action_group_exporter_set_events (GActionGroupExporter *exporter, source = g_idle_source_new (); exporter->pending_source = source; g_source_set_callback (source, g_action_group_exporter_dispatch_events, exporter, NULL); - g_source_attach (source, NULL); + g_source_attach (source, exporter->context); g_source_unref (source); } @@ -566,6 +567,7 @@ g_action_group_exporter_free (gpointer user_data) if (exporter->pending_source) g_source_destroy (exporter->pending_source); + g_main_context_unref (exporter->context); g_object_unref (exporter->connection); g_object_unref (exporter->action_group); g_free (exporter->object_path); @@ -585,7 +587,7 @@ g_action_group_exporter_free (gpointer user_data) * The implemented D-Bus API should be considered private. It is * subject to change in the future. * - * A given * object path can only have one action group exported on it. + * A given object path can only have one action group exported on it. * If this constraint is violated, the export will fail and 0 will be * returned (with @error set accordingly). * @@ -593,6 +595,15 @@ g_action_group_exporter_free (gpointer user_data) * g_dbus_connection_unexport_action_group() with the return value of * this function. * + * The thread default main context is taken at the time of this call. + * All incoming action activations and state change requests are + * reported from this context. Any changes on the action group that + * cause it to emit signals must also come from this same context. + * Since incoming action activations and state change requests are + * rather likely to cause changes on the action group, this effectively + * limits a given action group to being exported from only one main + * context. + * * Returns: the ID of the export (never zero), or 0 in case of failure * * Since: 2.32 @@ -633,6 +644,7 @@ g_dbus_connection_export_action_group (GDBusConnection *connection, return 0; } + exporter->context = g_main_context_ref_thread_default (); exporter->pending_changes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); exporter->pending_source = NULL; exporter->action_group = g_object_ref (action_group); diff --git a/gio/tests/actions.c b/gio/tests/actions.c index c9244382f..63ffe4855 100644 --- a/gio/tests/actions.c +++ b/gio/tests/actions.c @@ -624,33 +624,22 @@ test_dbus_export (void) g_object_unref (bus); } -static gpointer -do_activate (gpointer data) -{ - GSimpleActionGroup *group = data; - gint i; - GAction *action; - - for (i = 0; i < 1000000; i++) - { - action = g_simple_action_group_lookup (group, "a"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - !g_action_get_enabled (action)); - } - - return NULL; -} - static gpointer do_export (gpointer data) { GActionGroup *group = data; + GMainContext *ctx; gint i; GError *error = NULL; guint id; GDBusConnection *bus; + GAction *action; gchar *path; + ctx = g_main_context_new (); + + g_main_context_push_thread_default (ctx); + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); path = g_strdup_printf("/%p", data); @@ -658,12 +647,23 @@ do_export (gpointer data) { id = g_dbus_connection_export_action_group (bus, path, G_ACTION_GROUP (group), &error); g_assert_no_error (error); + + action = g_simple_action_group_lookup (G_SIMPLE_ACTION_GROUP (group), "a"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + !g_action_get_enabled (action)); + g_dbus_connection_unexport_action_group (bus, id); + + while (g_main_context_iteration (ctx, FALSE)); } g_free (path); g_object_unref (bus); + g_main_context_pop_thread_default (ctx); + + g_main_context_unref (ctx); + return NULL; } @@ -671,7 +671,6 @@ static void test_dbus_threaded (void) { GSimpleActionGroup *group[10]; - GThread *call[10]; GThread *export[10]; static GActionEntry entries[] = { { "a", activate_action, NULL, NULL, NULL }, @@ -683,15 +682,11 @@ test_dbus_threaded (void) { group[i] = g_simple_action_group_new (); g_simple_action_group_add_entries (group[i], entries, G_N_ELEMENTS (entries), NULL); - call[i] = g_thread_new ("call", do_activate, group[i]); export[i] = g_thread_new ("export", do_export, group[i]); } for (i = 0; i < 10; i++) - { - g_thread_join (call[i]); - g_thread_join (export[i]); - } + g_thread_join (export[i]); for (i = 0; i < 10; i++) g_object_unref (group[i]);