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.
This commit is contained in:
Thomas Haller 2017-02-04 20:42:42 +01:00
parent 6ad8011e2d
commit ecd3263e40
3 changed files with 46 additions and 15 deletions

View file

@ -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);

View file

@ -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__ */

View file

@ -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);