summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-02-04 20:42:42 +0100
committerThomas Haller <thaller@redhat.com>2017-02-10 15:26:45 +0100
commitecd3263e4011879a960419ed04d5f526c90d55e8 (patch)
treee1d8ee1d74874ddb091cf37365d6c41e630d183b
parent6ad8011e2dd3533860a4d98bd5de2528eecdd6cf (diff)
downloadNetworkManager-ecd3263e4011879a960419ed04d5f526c90d55e8.tar.gz
dns: fix shutdown to restore non-cached DNS config
The DNS manager and other singletons have the problem that they are not properly destroyed on exit, that is, we leak most of the instances. That should be eventually fixed and all resources/memory should be released. Anyway, fix the shutdown procedure by adding an explict command nm_dns_manager_shutdown(). We should not rely on cleanup actions to take place when the last reference is dropped, because then we get complex interactions where we must ensure that everybody drops the references at the right pointer. Since the previous shutdown action was effectively never performed, it is not quite clear what we actually want to do on shutdown. For now, move the code to nm_dns_manager_stop(). We will see if that is the desired behavior.
-rw-r--r--src/dns/nm-dns-manager.c56
-rw-r--r--src/dns/nm-dns-manager.h2
-rw-r--r--src/main.c3
3 files changed, 46 insertions, 15 deletions
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c
index cbf8d5fb6b..c990243ec7 100644
--- a/src/dns/nm-dns-manager.c
+++ b/src/dns/nm-dns-manager.c
@@ -130,7 +130,10 @@ typedef struct {
GPtrArray *configs;
GVariant *config_variant;
NMDnsIPConfigData *best_conf4, *best_conf6;
- gboolean need_sort;
+
+ bool need_sort:1;
+ bool dns_touched:1;
+ bool is_stopped:1;
char *hostname;
guint updates_queue;
@@ -144,8 +147,6 @@ typedef struct {
NMConfig *config;
- gboolean dns_touched;
-
struct {
guint64 ts;
guint num_restarts;
@@ -1124,6 +1125,11 @@ update_dns (NMDnsManager *self,
priv = NM_DNS_MANAGER_GET_PRIVATE (self);
+ if (priv->is_stopped) {
+ _LOGD ("update-dns: not updating resolv.conf (is stopped)");
+ return TRUE;
+ }
+
nm_clear_g_source (&priv->plugin_ratelimit.timer);
if (NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED,
@@ -1546,6 +1552,35 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func)
memset (priv->prev_hash, 0, sizeof (priv->prev_hash));
}
+void
+nm_dns_manager_stop (NMDnsManager *self)
+{
+ NMDnsManagerPrivate *priv;
+ GError *error = NULL;
+
+ priv = NM_DNS_MANAGER_GET_PRIVATE (self);
+
+ if (priv->is_stopped)
+ g_return_if_reached ();
+
+ _LOGT ("stopping...");
+
+ /* If we're quitting, leave a valid resolv.conf in place, not one
+ * pointing to 127.0.0.1 if any plugins were active. Thus update
+ * DNS after disposing of all plugins. But if we haven't done any
+ * DNS updates yet, there's no reason to touch resolv.conf on shutdown.
+ */
+ if (priv->dns_touched) {
+ if (!update_dns (self, TRUE, &error)) {
+ _LOGW ("could not commit DNS changes on shutdown: %s", error->message);
+ g_clear_error (&error);
+ }
+ priv->dns_touched = FALSE;
+ }
+
+ priv->is_stopped = TRUE;
+}
+
/*****************************************************************************/
static gboolean
@@ -2028,23 +2063,14 @@ dispose (GObject *object)
NMDnsManager *self = NM_DNS_MANAGER (object);
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
NMDnsIPConfigData *data;
- GError *error = NULL;
guint i;
_LOGT ("disposing");
- _clear_plugin (self);
+ if (!priv->is_stopped)
+ nm_dns_manager_stop (self);
- /* If we're quitting, leave a valid resolv.conf in place, not one
- * pointing to 127.0.0.1 if any plugins were active. Thus update
- * DNS after disposing of all plugins. But if we haven't done any
- * DNS updates yet, there's no reason to touch resolv.conf on shutdown.
- */
- if (priv->dns_touched && !update_dns (self, TRUE, &error)) {
- _LOGW ("could not commit DNS changes on shutdown: %s", error->message);
- g_clear_error (&error);
- priv->dns_touched = FALSE;
- }
+ _clear_plugin (self);
if (priv->config) {
g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self);
diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h
index 2fc2031b71..451ca4a658 100644
--- a/src/dns/nm-dns-manager.h
+++ b/src/dns/nm-dns-manager.h
@@ -120,4 +120,6 @@ typedef enum {
gboolean nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self);
+void nm_dns_manager_stop (NMDnsManager *self);
+
#endif /* __NETWORKMANAGER_DNS_MANAGER_H__ */
diff --git a/src/main.c b/src/main.c
index 20e6f30ff3..57902dd652 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,6 +49,7 @@
#include "nm-auth-manager.h"
#include "nm-core-internal.h"
#include "nm-exported-object.h"
+#include "dns/nm-dns-manager.h"
#include "systemd/nm-sd.h"
#if !defined(NM_DIST_VERSION)
@@ -434,6 +435,8 @@ done:
nm_config_state_set (config, TRUE, TRUE);
+ nm_dns_manager_stop (nm_dns_manager_get ());
+
if (global_opt.pidfile && wrote_pidfile)
unlink (global_opt.pidfile);