#define NETCONFIG_PATH "/sbin/netconfig"
#endif
+#define PLUGIN_RATELIMIT_INTERVAL 30
+#define PLUGIN_RATELIMIT_BURST 5
+#define PLUGIN_RATELIMIT_DELAY 300
+
NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager);
/*********************************************************************************************/
NMConfig *config;
gboolean dns_touched;
+
+ struct {
+ guint64 ts;
+ guint num_restarts;
+ guint timer;
+ } plugin_ratelimit;
} NMDnsManagerPrivate;
enum {
g_return_val_if_fail (!error || !*error, FALSE);
priv = NM_DNS_MANAGER_GET_PRIVATE (self);
+ nm_clear_g_source (&priv->plugin_ratelimit.timer);
if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED) {
update = FALSE;
}
}
-static void
-plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data)
+static gboolean
+plugin_child_quit_update_dns (gpointer user_data)
{
- NMDnsManager *self = NM_DNS_MANAGER (user_data);
GError *error = NULL;
-
- _LOGW ("plugin %s child quit unexpectedly; refreshing DNS",
- nm_dns_plugin_get_name (plugin));
+ NMDnsManager *self = NM_DNS_MANAGER (user_data);
/* Let the plugin try to spawn the child again */
if (!update_dns (self, FALSE, &error)) {
_LOGW ("could not commit DNS changes: %s", error->message);
g_clear_error (&error);
}
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data)
+{
+ NMDnsManager *self = NM_DNS_MANAGER (user_data);
+ NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
+ gint64 ts = nm_utils_get_monotonic_timestamp_ms ();
+
+ _LOGW ("plugin %s child quit unexpectedly", nm_dns_plugin_get_name (plugin));
+
+ if ( !priv->plugin_ratelimit.ts
+ || (ts - priv->plugin_ratelimit.ts) / 1000 > PLUGIN_RATELIMIT_INTERVAL) {
+ priv->plugin_ratelimit.ts = ts;
+ priv->plugin_ratelimit.num_restarts = 0;
+ } else {
+ priv->plugin_ratelimit.num_restarts++;
+ if (priv->plugin_ratelimit.num_restarts > PLUGIN_RATELIMIT_BURST) {
+ _LOGW ("plugin %s child respawning too fast, delaying update for %u seconds",
+ nm_dns_plugin_get_name (plugin), PLUGIN_RATELIMIT_DELAY);
+ priv->plugin_ratelimit.timer = g_timeout_add_seconds (PLUGIN_RATELIMIT_DELAY,
+ plugin_child_quit_update_dns,
+ self);
+ return;
+ }
+ }
+
+ plugin_child_quit_update_dns (self);
}
gboolean