mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +01:00 
			
		
		
		
	gdbusproxy: Add G_DBUS_PROXY_FLAGS_NO_MATCH_RULE flag
D-Bus has an upper limit on number of Match rules and it's rather easy to hit with a big number of proxies with signal subscriptions. This happens with NetworkManager with hundreds of devices or connection settings. By passing G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE to g_dbus_connection_signal_subscribe(), the user can call AddMatch with a less granular match instead of a match per every proxy. Tests subsequently added by Philip Withnall. Fixes: #1109
This commit is contained in:
		
				
					committed by
					
						 Philip Withnall
						Philip Withnall
					
				
			
			
				
	
			
			
			
						parent
						
							caf777984b
						
					
				
				
					commit
					a107a328e4
				
			| @@ -1694,6 +1694,10 @@ static void | ||||
| async_initable_init_first (GAsyncInitable *initable) | ||||
| { | ||||
|   GDBusProxy *proxy = G_DBUS_PROXY (initable); | ||||
|   GDBusSignalFlags signal_flags = G_DBUS_SIGNAL_FLAGS_NONE; | ||||
|  | ||||
|   if (proxy->priv->flags & G_DBUS_PROXY_FLAGS_NO_MATCH_RULE) | ||||
|     signal_flags |= G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE; | ||||
|  | ||||
|   if (!(proxy->priv->flags & G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)) | ||||
|     { | ||||
| @@ -1705,7 +1709,7 @@ async_initable_init_first (GAsyncInitable *initable) | ||||
|                                             "PropertiesChanged", | ||||
|                                             proxy->priv->object_path, | ||||
|                                             proxy->priv->interface_name, | ||||
|                                             G_DBUS_SIGNAL_FLAGS_NONE, | ||||
|                                             signal_flags, | ||||
|                                             on_properties_changed, | ||||
|                                             weak_ref_new (G_OBJECT (proxy)), | ||||
|                                             (GDestroyNotify) weak_ref_free); | ||||
| @@ -1721,7 +1725,7 @@ async_initable_init_first (GAsyncInitable *initable) | ||||
|                                             NULL,                        /* member */ | ||||
|                                             proxy->priv->object_path, | ||||
|                                             NULL,                        /* arg0 */ | ||||
|                                             G_DBUS_SIGNAL_FLAGS_NONE, | ||||
|                                             signal_flags, | ||||
|                                             on_signal_received, | ||||
|                                             weak_ref_new (G_OBJECT (proxy)), | ||||
|                                             (GDestroyNotify) weak_ref_free); | ||||
| @@ -1737,7 +1741,7 @@ async_initable_init_first (GAsyncInitable *initable) | ||||
|                                             "NameOwnerChanged",      /* signal name */ | ||||
|                                             "/org/freedesktop/DBus", /* path */ | ||||
|                                             proxy->priv->name,       /* arg0 */ | ||||
|                                             G_DBUS_SIGNAL_FLAGS_NONE, | ||||
|                                             signal_flags, | ||||
|                                             on_name_owner_changed, | ||||
|                                             weak_ref_new (G_OBJECT (proxy)), | ||||
|                                             (GDestroyNotify) weak_ref_free); | ||||
|   | ||||
| @@ -1021,6 +1021,9 @@ typedef enum | ||||
|  * do not ask the bus to launch an owner during proxy initialization, but allow it to be | ||||
|  * autostarted by a method call. This flag is only meaningful in proxies for well-known names, | ||||
|  * and only if %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START is not also specified. | ||||
|  * @G_DBUS_PROXY_FLAGS_NO_MATCH_RULE: Don't actually send the AddMatch D-Bus | ||||
|  *    call for this signal subscription. This gives you more control | ||||
|  *    over which match rules you add (but you must add them manually). (Since: 2.72) | ||||
|  * | ||||
|  * Flags used when constructing an instance of a #GDBusProxy derived class. | ||||
|  * | ||||
| @@ -1033,7 +1036,8 @@ typedef enum | ||||
|   G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS = (1<<1), | ||||
|   G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START = (1<<2), | ||||
|   G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES = (1<<3), | ||||
|   G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION = (1<<4) | ||||
|   G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION = (1<<4), | ||||
|   G_DBUS_PROXY_FLAGS_NO_MATCH_RULE GLIB_AVAILABLE_ENUMERATOR_IN_2_72 = (1<<5) | ||||
| } GDBusProxyFlags; | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -701,7 +701,6 @@ test_basic (GDBusProxy *proxy) | ||||
|   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); | ||||
|  | ||||
|   g_assert_true (g_dbus_proxy_get_connection (proxy) == connection); | ||||
|   g_assert_cmpint (g_dbus_proxy_get_flags (proxy), ==, G_DBUS_PROXY_FLAGS_NONE); | ||||
|   g_assert_null (g_dbus_proxy_get_interface_info (proxy)); | ||||
|   g_assert_cmpstr (g_dbus_proxy_get_name (proxy), ==, "com.example.TestService"); | ||||
|   g_assert_cmpstr (g_dbus_proxy_get_object_path (proxy), ==, "/com/example/TestObject"); | ||||
| @@ -720,7 +719,7 @@ test_basic (GDBusProxy *proxy) | ||||
|  | ||||
|   g_assert_true (conn == connection); | ||||
|   g_assert_null (info); | ||||
|   g_assert_cmpint (flags, ==, G_DBUS_PROXY_FLAGS_NONE); | ||||
|   g_assert_cmpint (flags, ==, g_dbus_proxy_get_flags (proxy)); | ||||
|   g_assert_cmpstr (name, ==, "com.example.TestService"); | ||||
|   g_assert_cmpstr (path, ==, "/com/example/TestObject"); | ||||
|   g_assert_cmpstr (interface, ==, "com.example.Frob"); | ||||
| @@ -763,7 +762,7 @@ kill_test_service (GDBusConnection *connection) | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_proxy (void) | ||||
| test_proxy_with_flags (GDBusProxyFlags flags) | ||||
| { | ||||
|   GDBusProxy *proxy; | ||||
|   GDBusConnection *connection; | ||||
| @@ -777,7 +776,7 @@ test_proxy (void) | ||||
|   g_assert_no_error (error); | ||||
|   error = NULL; | ||||
|   proxy = g_dbus_proxy_new_sync (connection, | ||||
|                                  G_DBUS_PROXY_FLAGS_NONE, | ||||
|                                  flags, | ||||
|                                  NULL,                      /* GDBusInterfaceInfo */ | ||||
|                                  "com.example.TestService", /* name */ | ||||
|                                  "/com/example/TestObject", /* object path */ | ||||
| @@ -809,6 +808,12 @@ test_proxy (void) | ||||
|   g_object_unref (connection); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_proxy (void) | ||||
| { | ||||
|   test_proxy_with_flags (G_DBUS_PROXY_FLAGS_NONE); | ||||
| } | ||||
|  | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
|  | ||||
| static void | ||||
| @@ -930,6 +935,58 @@ test_wellknown_noauto (void) | ||||
|   g_source_remove (id); | ||||
| } | ||||
|  | ||||
| typedef enum { | ||||
|   ADD_MATCH, | ||||
|   REMOVE_MATCH, | ||||
| } AddOrRemove; | ||||
|  | ||||
| static void | ||||
| add_or_remove_match_rule (GDBusConnection *connection, | ||||
|                           AddOrRemove      add_or_remove, | ||||
|                           GVariant        *match_rule) | ||||
| { | ||||
|   GDBusMessage *message = NULL; | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   message = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */ | ||||
|                                             "/org/freedesktop/DBus", /* path */ | ||||
|                                             "org.freedesktop.DBus", /* interface */ | ||||
|                                             (add_or_remove == ADD_MATCH) ? "AddMatch" : "RemoveMatch"); | ||||
|   g_dbus_message_set_body (message, match_rule); | ||||
|   g_dbus_connection_send_message (connection, | ||||
|                                   message, | ||||
|                                   G_DBUS_SEND_MESSAGE_FLAGS_NONE, | ||||
|                                   NULL, | ||||
|                                   &error); | ||||
|   g_assert_no_error (error); | ||||
|   g_clear_object (&message); | ||||
| } | ||||
|  | ||||
| static void | ||||
| test_proxy_no_match_rule (void) | ||||
| { | ||||
|   GDBusConnection *connection = NULL; | ||||
|   GVariant *match_rule = NULL; | ||||
|  | ||||
|   g_test_summary ("Test that G_DBUS_PROXY_FLAGS_NO_MATCH_RULE works"); | ||||
|   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/1109"); | ||||
|  | ||||
|   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); | ||||
|  | ||||
|   /* Add a custom match rule which matches everything. */ | ||||
|   match_rule = g_variant_ref_sink (g_variant_new ("(s)", "type='signal'")); | ||||
|   add_or_remove_match_rule (connection, ADD_MATCH, match_rule); | ||||
|  | ||||
|   /* Run the tests. */ | ||||
|   test_proxy_with_flags (G_DBUS_PROXY_FLAGS_NO_MATCH_RULE); | ||||
|  | ||||
|   /* Remove the match rule again. */ | ||||
|   add_or_remove_match_rule (connection, REMOVE_MATCH, match_rule); | ||||
|  | ||||
|   g_clear_pointer (&match_rule, g_variant_unref); | ||||
|   g_clear_object (&connection); | ||||
| } | ||||
|  | ||||
| int | ||||
| main (int   argc, | ||||
|       char *argv[]) | ||||
| @@ -950,6 +1007,7 @@ main (int   argc, | ||||
|   g_test_add_func ("/gdbus/proxy/no-properties", test_no_properties); | ||||
|   g_test_add_func ("/gdbus/proxy/wellknown-noauto", test_wellknown_noauto); | ||||
|   g_test_add_func ("/gdbus/proxy/async", test_async); | ||||
|   g_test_add_func ("/gdbus/proxy/no-match-rule", test_proxy_no_match_rule); | ||||
|  | ||||
|   ret = session_bus_run(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user