From ffe52feea851d047dbff66b8096672ae4f1ac268 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 3 Jul 2017 09:14:50 +0200 Subject: dns: replace the FAILED and CHILD_QUIT signals with a STATE property When we'll supporting multiple DNS plugins, we'll need to know whether a particular plugin is in a workable state instead of just reacting to state change events. --- src/dns/nm-dns-dnsmasq.c | 6 ++- src/dns/nm-dns-manager.c | 50 +++++++++--------- src/dns/nm-dns-plugin.c | 106 +++++++++++++++++++++++++++----------- src/dns/nm-dns-plugin.h | 12 ++++- src/dns/nm-dns-systemd-resolved.c | 3 +- src/dns/nm-dns-unbound.c | 11 +++- 6 files changed, 127 insertions(+), 61 deletions(-) diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index df3ca11120..91a42a6e61 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -430,8 +430,10 @@ name_owner_changed (GObject *object, } else { _LOGI ("dnsmasq disappeared"); priv->running = FALSE; - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); } + + nm_dns_plugin_set_state (NM_DNS_PLUGIN (self), + priv->running ? NM_DNS_PLUGIN_STATE_RUNNING : NM_DNS_PLUGIN_STATE_FAILED); } static void @@ -452,7 +454,7 @@ dnsmasq_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data) if (!proxy) { _LOGW ("failed to connect to dnsmasq via DBus: %s", error->message); - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); + nm_dns_plugin_set_state (NM_DNS_PLUGIN (self), NM_DNS_PLUGIN_STATE_FAILED); return; } diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index f5776d13a7..e048f9bc78 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -147,6 +147,8 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, NM_TYPE_EXPORTED_OBJECT) #define NM_DNS_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDnsManager, NM_IS_DNS_MANAGER) +static void plugin_state_changed (NMDnsPlugin *plugin, GParamSpec *pspec, gpointer user_data); + static gboolean domain_is_valid (const gchar *domain) { @@ -1132,6 +1134,7 @@ update_dns (NMDnsManager *self, caching = TRUE; _LOGD ("update-dns: updating plugin %s", plugin_name); + g_signal_handlers_block_by_func (plugin, plugin_state_changed, self); if (!nm_dns_plugin_update (plugin, priv->configs, global_config, @@ -1143,6 +1146,7 @@ update_dns (NMDnsManager *self, */ caching = FALSE; } + g_signal_handlers_unblock_by_func (plugin, plugin_state_changed, self); skip: ; @@ -1204,28 +1208,29 @@ update_dns (NMDnsManager *self, } static void -plugin_failed (NMDnsPlugin *plugin, gpointer user_data) -{ - NMDnsManager *self = NM_DNS_MANAGER (user_data); - GError *error = NULL; - - /* Disable caching until the next DNS update */ - if (!update_dns (self, TRUE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } -} - -static void -plugin_child_quit (NMDnsPlugin *plugin, gpointer user_data) +plugin_state_changed (NMDnsPlugin *plugin, GParamSpec *pspec, gpointer user_data) { NMDnsManager *self = NM_DNS_MANAGER (user_data); GError *error = NULL; + const char *plugin_name = nm_dns_plugin_get_name (plugin); - /* 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); + switch (nm_dns_plugin_get_state (plugin)) { + case NM_DNS_PLUGIN_STATE_STOPPED: + _LOGI ("dns: plugin %s stopped, restarting it", plugin_name); + if (!update_dns (self, FALSE, &error)) { + _LOGW ("could not commit DNS changes: %s", error->message); + g_clear_error (&error); + } + break; + case NM_DNS_PLUGIN_STATE_FAILED: + _LOGW ("dns: plugin %s failed", plugin_name); + if (!update_dns (self, TRUE, &error)) { + _LOGW ("could not commit DNS changes: %s", error->message); + g_clear_error (&error); + } + break; + default: + return; } } @@ -1524,8 +1529,7 @@ _clear_plugin (NMDnsManager *self) NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); if (priv->plugin) { - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self); - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self); + g_signal_handlers_disconnect_by_func (priv->plugin, plugin_state_changed, self); nm_dns_plugin_stop (priv->plugin); g_clear_object (&priv->plugin); return TRUE; @@ -1725,10 +1729,8 @@ again: plugin_changed = TRUE; } - if (plugin_changed && priv->plugin) { - g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); - g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self); - } + if (plugin_changed && priv->plugin) + g_signal_connect (priv->plugin, "notify::" NM_DNS_PLUGIN_STATE, G_CALLBACK (plugin_state_changed), self); g_object_freeze_notify (G_OBJECT (self)); diff --git a/src/dns/nm-dns-plugin.c b/src/dns/nm-dns-plugin.c index 6d65913d51..a998da5807 100644 --- a/src/dns/nm-dns-plugin.c +++ b/src/dns/nm-dns-plugin.c @@ -36,19 +36,16 @@ #define PLUGIN_RATELIMIT_BURST 5 #define PLUGIN_RATELIMIT_DELAY 300 -enum { - FAILED, - CHILD_QUIT, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = { 0 }; +NM_GOBJECT_PROPERTIES_DEFINE (NMDnsPlugin, + PROP_STATE, +); typedef struct _NMDnsPluginPrivate { GPid pid; guint watch_id; char *progname; char *pidfile; + NMDnsPluginState state; struct { guint64 ts; @@ -173,7 +170,7 @@ emit_ratelimited_child_quit (gpointer user_data) { NMDnsPlugin *self = NM_DNS_PLUGIN (user_data); - g_signal_emit (self, signals[CHILD_QUIT], 0); + nm_dns_plugin_set_state (self, NM_DNS_PLUGIN_STATE_STOPPED); return G_SOURCE_REMOVE; } @@ -213,9 +210,9 @@ watch_cb (GPid pid, gint status, gpointer user_data) } if (failed) - g_signal_emit (self, signals[FAILED], 0); + nm_dns_plugin_set_state (self, NM_DNS_PLUGIN_STATE_FAILED); else - g_signal_emit (self, signals[CHILD_QUIT], 0); + nm_dns_plugin_set_state (self, NM_DNS_PLUGIN_STATE_STOPPED); } /*****************************************************************************/ @@ -307,6 +304,64 @@ nm_dns_plugin_stop (NMDnsPlugin *self) /*****************************************************************************/ +NMDnsPluginState +nm_dns_plugin_get_state (NMDnsPlugin *self) +{ + NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); + + return priv->state; +} + +void +nm_dns_plugin_set_state (NMDnsPlugin *self, NMDnsPluginState state) +{ + NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); + + if (priv->state == state) + return; + + priv->state = state; + _notify (self, PROP_STATE); +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDnsPlugin *self = NM_DNS_PLUGIN (object); + NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_STATE: + g_value_set_uint (value, priv->state); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDnsPlugin *self = NM_DNS_PLUGIN (object); + NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_STATE: + priv->state = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + static void nm_dns_plugin_init (NMDnsPlugin *self) { @@ -330,26 +385,17 @@ nm_dns_plugin_class_init (NMDnsPluginClass *plugin_class) g_type_class_add_private (plugin_class, sizeof (NMDnsPluginPrivate)); + object_class->get_property = get_property; + object_class->set_property = set_property; object_class->dispose = dispose; - /* Emitted by the plugin and consumed by NMDnsManager when - * some error happens with the nameserver subprocess. Causes NM to fall - * back to writing out a non-local-caching resolv.conf until the next - * DNS update. - */ - signals[FAILED] = - g_signal_new (NM_DNS_PLUGIN_FAILED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[CHILD_QUIT] = - g_signal_new (NM_DNS_PLUGIN_CHILD_QUIT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + obj_properties[PROP_STATE] = + g_param_spec_uint (NM_DNS_PLUGIN_STATE, "", "", + NM_DNS_PLUGIN_STATE_STOPPED, + NM_DNS_PLUGIN_STATE_FAILED, + NM_DNS_PLUGIN_STATE_STOPPED, + G_PARAM_READABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/dns/nm-dns-plugin.h b/src/dns/nm-dns-plugin.h index c37c657e01..e4a6cd40fa 100644 --- a/src/dns/nm-dns-plugin.h +++ b/src/dns/nm-dns-plugin.h @@ -29,8 +29,7 @@ #define NM_IS_DNS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DNS_PLUGIN)) #define NM_DNS_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass)) -#define NM_DNS_PLUGIN_FAILED "failed" -#define NM_DNS_PLUGIN_CHILD_QUIT "child-quit" +#define NM_DNS_PLUGIN_STATE "state" struct _NMDnsPluginPrivate; @@ -64,10 +63,19 @@ typedef struct { gboolean (*child_quit) (NMDnsPlugin *self, gint status); } NMDnsPluginClass; +typedef enum { + NM_DNS_PLUGIN_STATE_STOPPED, + NM_DNS_PLUGIN_STATE_RUNNING, + NM_DNS_PLUGIN_STATE_FAILED, +} NMDnsPluginState; + GType nm_dns_plugin_get_type (void); const char *nm_dns_plugin_get_name (NMDnsPlugin *self); +NMDnsPluginState nm_dns_plugin_get_state (NMDnsPlugin *self); +void nm_dns_plugin_set_state (NMDnsPlugin *self, NMDnsPluginState state); + gboolean nm_dns_plugin_update (NMDnsPlugin *self, const GPtrArray *configs, const NMGlobalDnsConfig *global_config, diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c index d090de3f80..a48f78d259 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/dns/nm-dns-systemd-resolved.c @@ -353,10 +353,11 @@ resolved_proxy_created (GObject *source, GAsyncResult *r, gpointer user_data) g_clear_object (&priv->init_cancellable); if (!resolve) { _LOGW ("failed to connect to resolved via DBus: %s", error->message); - g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED); + nm_dns_plugin_set_state (NM_DNS_PLUGIN (self), NM_DNS_PLUGIN_STATE_FAILED); return; } + nm_dns_plugin_set_state (NM_DNS_PLUGIN (self), NM_DNS_PLUGIN_STATE_RUNNING); priv->resolve = resolve; send_updates (self); } diff --git a/src/dns/nm-dns-unbound.c b/src/dns/nm-dns-unbound.c index 0d2dc0adb2..e86e51e08a 100644 --- a/src/dns/nm-dns-unbound.c +++ b/src/dns/nm-dns-unbound.c @@ -45,6 +45,7 @@ update (NMDnsPlugin *plugin, { char *argv[] = { DNSSEC_TRIGGER_SCRIPT, "--async", "--update", NULL }; int status; + gboolean success; /* TODO: We currently call a script installed with the dnssec-trigger * package that queries all information itself. Later, the dependency @@ -56,8 +57,14 @@ update (NMDnsPlugin *plugin, * may be eventually merged into NetworkManager. */ if (!g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, NULL)) - return FALSE; - return (status == 0); + success = FALSE; + else + success = (status == 0); + + nm_dns_plugin_set_state (plugin, + success ? NM_DNS_PLUGIN_STATE_RUNNING : NM_DNS_PLUGIN_STATE_FAILED); + + return success; } static const char * -- cgit v1.2.1