summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2015-11-27 18:01:52 +0100
committerLubomir Rintel <lkundrak@v3.sk>2015-11-30 16:56:20 +0100
commit48d5291fca52431049c8380ea19207b9d564886d (patch)
tree4b4d412eaa475a8d65c99eb27624b5d5bff3a931
parent7e93ceb6408cd9345222066ade3f76cc38ad7db3 (diff)
downloadNetworkManager-lr/add-match-craze.tar.gz
libnm: avoid loosing signalslr/add-match-craze
GDBus adds a huge number of lalala D-Bus has an upper limit on number of Match rules and it's rather easy to hit as the proxy likes to add one for each object. Let's remove the Match rule the proxy added and ensure a less granular rule is present instead. Ideally, we should be able to tell glib not to hook its rules. Related: https://bugzilla.gnome.org/show_bug.cgi?id=758749
-rw-r--r--libnm/nm-dbus-helpers.c88
-rw-r--r--src/org.freedesktop.NetworkManager.conf1
2 files changed, 79 insertions, 10 deletions
diff --git a/libnm/nm-dbus-helpers.c b/libnm/nm-dbus-helpers.c
index a105f95c25..3c0393752d 100644
--- a/libnm/nm-dbus-helpers.c
+++ b/libnm/nm-dbus-helpers.c
@@ -25,6 +25,7 @@
#include "nm-default.h"
#include "nm-dbus-helpers.h"
#include "nm-dbus-interface.h"
+#include "nm-macros-internal.h"
static GBusType nm_bus = G_BUS_TYPE_SYSTEM;
@@ -116,6 +117,67 @@ _nm_dbus_register_proxy_type (const char *interface,
#define NM_DBUS_PROXY_FLAGS (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | \
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
+/* D-Bus has an upper limit on number of Match rules and it's rather easy
+ * to hit as the proxy likes to add one for each object. Let's remove the Match
+ * rule the proxy added and ensure a less granular rule is present instead.
+ *
+ * Also, don't do this immediately since it has a performance penalty.
+ * Still better than loosing the signals altogether.
+ *
+ * Ideally, we should be able to tell glib not to hook its rules:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=758749
+ */
+static void
+_nm_dbus_proxy_replace_match (GDBusProxy *proxy)
+{
+ GDBusConnection *connection = g_dbus_proxy_get_connection (proxy);
+ static unsigned match_counter = 1024;
+ gchar *match;
+
+ nm_assert (!g_strcmp0 (g_dbus_proxy_get_name (proxy), NM_DBUS_SERVICE));
+
+ if (match_counter == 1) {
+ /* If we hit the low matches watermark, install a
+ * less granular one. */
+ g_dbus_connection_call (connection,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "AddMatch",
+ g_variant_new ("(s)", "type='signal',sender='" NM_DBUS_SERVICE "'"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+ }
+
+ if (match_counter)
+ match_counter--;
+ if (match_counter)
+ return;
+
+ /* Remove what this proxy added. */
+ match = g_strdup_printf ("type='signal',sender='" NM_DBUS_SERVICE "',"
+ "interface='%s',path='%s'",
+ g_dbus_proxy_get_interface_name (proxy),
+ g_dbus_proxy_get_object_path (proxy));
+ g_dbus_connection_call (connection,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "RemoveMatch",
+ g_variant_new ("(s)", match),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+ g_free (match);
+}
+
GDBusProxy *
_nm_dbus_new_proxy_for_connection (GDBusConnection *connection,
const char *path,
@@ -123,6 +185,7 @@ _nm_dbus_new_proxy_for_connection (GDBusConnection *connection,
GCancellable *cancellable,
GError **error)
{
+ GDBusProxy *proxy;
GType proxy_type;
const char *name;
@@ -135,13 +198,16 @@ _nm_dbus_new_proxy_for_connection (GDBusConnection *connection,
else
name = NM_DBUS_SERVICE;
- return g_initable_new (proxy_type, cancellable, error,
- "g-connection", connection,
- "g-flags", NM_DBUS_PROXY_FLAGS,
- "g-name", name,
- "g-object-path", path,
- "g-interface-name", interface,
- NULL);
+ proxy = g_initable_new (proxy_type, cancellable, error,
+ "g-connection", connection,
+ "g-flags", NM_DBUS_PROXY_FLAGS,
+ "g-name", name,
+ "g-object-path", path,
+ "g-interface-name", interface,
+ NULL);
+ _nm_dbus_proxy_replace_match (proxy);
+
+ return proxy;
}
void
@@ -178,13 +244,15 @@ GDBusProxy *
_nm_dbus_new_proxy_for_connection_finish (GAsyncResult *result,
GError **error)
{
- GObject *source, *proxy;
+ GObject *source;
+ GDBusProxy *proxy;
source = g_async_result_get_source_object (result);
- proxy = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error);
+ proxy = G_DBUS_PROXY (g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error));
g_object_unref (source);
+ _nm_dbus_proxy_replace_match (proxy);
- return G_DBUS_PROXY (proxy);
+ return proxy;
}
/* Binds the properties on a generated server-side GDBus object to the
diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf
index c4082d2b50..801d9a7dab 100644
--- a/src/org.freedesktop.NetworkManager.conf
+++ b/src/org.freedesktop.NetworkManager.conf
@@ -123,5 +123,6 @@
</policy>
<limit name="max_replies_per_connection">1024</limit>
+ <limit name="max_match_rules_per_connection">2048</limit>
</busconfig>