diff --git a/gio/gmenuexporter.c b/gio/gmenuexporter.c index 909780cb2..1d4db1352 100644 --- a/gio/gmenuexporter.c +++ b/gio/gmenuexporter.c @@ -707,11 +707,9 @@ g_menu_exporter_create_group (GMenuExporter *exporter) } static void -g_menu_exporter_free (gpointer user_data) +g_menu_exporter_free (GMenuExporter *exporter) { - GMenuExporter *exporter = user_data; - - g_menu_exporter_menu_free (exporter->root); + g_clear_pointer (&exporter->root, g_menu_exporter_menu_free); g_clear_pointer (&exporter->peer_remote, g_menu_exporter_remote_free); g_hash_table_unref (exporter->remotes); g_hash_table_unref (exporter->groups); @@ -794,21 +792,16 @@ g_dbus_connection_export_menu_model (GDBusConnection *connection, guint id; exporter = g_slice_new0 (GMenuExporter); - - id = g_dbus_connection_register_object (connection, object_path, org_gtk_Menus_get_interface (), - &vtable, exporter, g_menu_exporter_free, error); - - if (id == 0) - { - g_slice_free (GMenuExporter, exporter); - return 0; - } - exporter->connection = g_object_ref (connection); exporter->object_path = g_strdup (object_path); exporter->groups = g_hash_table_new (NULL, NULL); exporter->remotes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_menu_exporter_remote_free); - exporter->root = g_menu_exporter_group_add_menu (g_menu_exporter_create_group (exporter), menu); + + id = g_dbus_connection_register_object (connection, object_path, org_gtk_Menus_get_interface (), + &vtable, exporter, (GDestroyNotify) g_menu_exporter_free, error); + + if (id != 0) + exporter->root = g_menu_exporter_group_add_menu (g_menu_exporter_create_group (exporter), menu); return id; } diff --git a/gio/tests/gmenumodel.c b/gio/tests/gmenumodel.c index d75f36a29..22d1b4d61 100644 --- a/gio/tests/gmenumodel.c +++ b/gio/tests/gmenumodel.c @@ -1159,6 +1159,42 @@ test_dbus_peer_subscriptions (void) #endif } +static void +test_dbus_export_error_handling (void) +{ + GRand *rand = NULL; + RandomMenu *menu = NULL; + GDBusConnection *bus; + GError *local_error = NULL; + guint id1, id2; + + g_test_summary ("Test that error handling of menu model export failure works"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3366"); + + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + + rand = g_rand_new_with_seed (g_test_rand_int ()); + menu = random_menu_new (rand, 2); + + id1 = g_dbus_connection_export_menu_model (bus, "/", G_MENU_MODEL (menu), &local_error); + g_assert_no_error (local_error); + g_assert_cmpuint (id1, !=, 0); + + /* Trigger a failure by trying to export on a path which is already in use */ + id2 = g_dbus_connection_export_menu_model (bus, "/", G_MENU_MODEL (menu), &local_error); + g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS); + g_assert_cmpuint (id2, ==, 0); + g_clear_error (&local_error); + + g_dbus_connection_unexport_menu_model (bus, id1); + + while (g_main_context_iteration (NULL, FALSE)); + + g_clear_object (&menu); + g_rand_free (rand); + g_clear_object (&bus); +} + static gpointer do_modify (gpointer data) { @@ -1658,6 +1694,7 @@ main (int argc, char **argv) g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded); g_test_add_func ("/gmenu/dbus/peer/roundtrip", test_dbus_peer_roundtrip); g_test_add_func ("/gmenu/dbus/peer/subscriptions", test_dbus_peer_subscriptions); + g_test_add_func ("/gmenu/dbus/export/error-handling", test_dbus_export_error_handling); g_test_add_func ("/gmenu/attributes", test_attributes); g_test_add_func ("/gmenu/attributes/iterate", test_attribute_iter); g_test_add_func ("/gmenu/links", test_links);