summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-07-24 18:54:13 +0200
committerThomas Haller <thaller@redhat.com>2015-08-05 15:23:57 +0200
commit2cf274c03eb93877f835113d8429b938495b9091 (patch)
tree7c5336ef217a498954194069c020921a7e337b32
parente0bded93f347154fdd5e2a5c2811ff49942f24d5 (diff)
downloadNetworkManager-2cf274c03eb93877f835113d8429b938495b9091.tar.gz
core: order destruction of singleton instances
Previously, the order of destructing singleton instances was undefined. Now, have singleton instances register their destruction via nm_singleton_instance_register(). Objects that are registered later, will be destructed earlier. IOW, they will be destroyed in reverse order of construction. This is only a crude method to get the lifetime of singleton instances right by default. Having singletons ref other singletons to keep them alive gives more control over the lifetimes of singletons. This change of having a defined order of destruction does not conflict with taking references to singletons (and thus extending their lifetime). Note that previously, NMPlatform was not registered for destruction. We don't change that yet and intenionally leak a reference.
-rw-r--r--src/NetworkManagerUtils.c47
-rw-r--r--src/NetworkManagerUtils.h24
-rw-r--r--src/main.c6
-rw-r--r--src/nm-auth-manager.c5
-rw-r--r--src/nm-bus-manager.c5
-rw-r--r--src/nm-config.c5
-rw-r--r--src/platform/nm-platform.c4
7 files changed, 68 insertions, 28 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index c866c5f496..c9a7e13fed 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -112,6 +112,53 @@ _nm_utils_set_testing (NMUtilsTestFlags flags)
}
}
+/*****************************************************************************/
+
+static GSList *_singletons = NULL;
+static gboolean _singletons_shutdown = FALSE;
+
+static void
+_nm_singleton_instance_weak_cb (gpointer data,
+ GObject *where_the_object_was)
+{
+ _singletons = g_slist_remove (_singletons, where_the_object_was);
+}
+
+static void __attribute__((destructor))
+_nm_singleton_instance_destroy (void)
+{
+ _singletons_shutdown = TRUE;
+
+ while (_singletons) {
+ GObject *instance = _singletons->data;
+
+ _singletons = g_slist_delete_link (_singletons, _singletons);
+
+ g_object_weak_unref (instance, _nm_singleton_instance_weak_cb, NULL);
+
+ if (instance->ref_count > 1)
+ nm_log_dbg (LOGD_CORE, "disown %s singleton (%p). There are more references and the instance might leak", G_OBJECT_TYPE_NAME (instance), instance);
+
+ g_object_unref (instance);
+ }
+}
+
+void
+_nm_singleton_instance_register_destruction (GObject *instance)
+{
+ g_return_if_fail (G_IS_OBJECT (instance));
+
+ /* Don't allow registration after shutdown. We only destroy the singletons
+ * once. */
+ g_return_if_fail (!_singletons_shutdown);
+
+ g_object_weak_ref (instance, _nm_singleton_instance_weak_cb, NULL);
+
+ _singletons = g_slist_prepend (_singletons, instance);
+}
+
+/*****************************************************************************/
+
/*
* nm_ethernet_address_is_valid:
* @addr: pointer to a binary or ASCII Ethernet address
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 5cc34cdf69..118534b8b3 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -34,7 +34,7 @@
#define NM_DEFINE_SINGLETON_INSTANCE(TYPE) \
static TYPE *singleton_instance
-#define NM_DEFINE_SINGLETON_WEAK_REF(TYPE) \
+#define NM_DEFINE_SINGLETON_REGISTER(TYPE) \
NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
static void \
_singleton_instance_weak_ref_cb (gpointer data, \
@@ -44,22 +44,13 @@ _singleton_instance_weak_ref_cb (gpointer data, \
singleton_instance = NULL; \
} \
static inline void \
-nm_singleton_instance_weak_ref_register (void) \
+nm_singleton_instance_register () \
{ \
g_object_weak_ref (G_OBJECT (singleton_instance), _singleton_instance_weak_ref_cb, NULL); \
+ _nm_singleton_instance_register_destruction (G_OBJECT (singleton_instance)); \
}
-#define NM_DEFINE_SINGLETON_DESTRUCTOR(TYPE) \
-NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
-static void __attribute__((destructor)) \
-_singleton_destructor (void) \
-{ \
- if (singleton_instance) { \
- if (G_OBJECT (singleton_instance)->ref_count > 1) \
- nm_log_dbg (LOGD_CORE, "disown %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
- g_object_unref (singleton_instance); \
- } \
-}
+void _nm_singleton_instance_register_destruction (GObject *instance);
/* By default, the getter will assert that the singleton will be created only once. You can
* change this by redefining NM_DEFINE_SINGLETON_ALLOW_MULTIPLE. */
@@ -69,7 +60,7 @@ _singleton_destructor (void) \
#define NM_DEFINE_SINGLETON_GETTER(TYPE, GETTER, GTYPE, ...) \
NM_DEFINE_SINGLETON_INSTANCE (TYPE); \
-NM_DEFINE_SINGLETON_WEAK_REF (TYPE); \
+NM_DEFINE_SINGLETON_REGISTER (TYPE); \
TYPE * \
GETTER (void) \
{ \
@@ -80,12 +71,11 @@ GETTER (void) \
_already_created = TRUE;\
singleton_instance = (g_object_new (GTYPE, ##__VA_ARGS__, NULL)); \
g_assert (singleton_instance); \
- nm_singleton_instance_weak_ref_register (); \
+ nm_singleton_instance_register (); \
nm_log_dbg (LOGD_CORE, "create %s singleton (%p)", G_STRINGIFY (TYPE), singleton_instance); \
} \
return singleton_instance; \
-} \
-NM_DEFINE_SINGLETON_DESTRUCTOR(TYPE)
+}
/*****************************************************************************/
diff --git a/src/main.c b/src/main.c
index a0b6e37553..9f6ebdf3d2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -440,6 +440,12 @@ main (int argc, char *argv[])
/* Set up platform interaction layer */
nm_linux_platform_setup ();
+ /* FIXME: intentionally leak the singleton instance of NMPlatform.
+ * nm_linux_platform_setup() will register the singleton for destruction,
+ * but we don't yet shut down all singletons properly, so don't destroy
+ * NMPlatform. */
+ g_object_ref (NM_PLATFORM_GET);
+
nm_auth_manager_setup (nm_config_get_auth_polkit (config));
nm_dispatcher_init ();
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c
index 9caca771f4..298bc096fe 100644
--- a/src/nm-auth-manager.c
+++ b/src/nm-auth-manager.c
@@ -78,8 +78,7 @@ typedef struct {
#endif
} NMAuthManagerPrivate;
-NM_DEFINE_SINGLETON_DESTRUCTOR (NMAuthManager);
-NM_DEFINE_SINGLETON_WEAK_REF (NMAuthManager);
+NM_DEFINE_SINGLETON_REGISTER (NMAuthManager);
G_DEFINE_TYPE (NMAuthManager, nm_auth_manager, G_TYPE_OBJECT)
@@ -499,7 +498,7 @@ nm_auth_manager_setup (gboolean polkit_enabled)
_LOGD ("set instance");
singleton_instance = self;
- nm_singleton_instance_weak_ref_register ();
+ nm_singleton_instance_register ();
return self;
}
diff --git a/src/nm-bus-manager.c b/src/nm-bus-manager.c
index a600c225d4..e604746c18 100644
--- a/src/nm-bus-manager.c
+++ b/src/nm-bus-manager.c
@@ -78,8 +78,7 @@ static void nm_bus_manager_cleanup (NMBusManager *self, gboolean dispose);
static void start_reconnection_timeout (NMBusManager *self);
static void object_destroyed (NMBusManager *self, gpointer object);
-NM_DEFINE_SINGLETON_DESTRUCTOR (NMBusManager);
-NM_DEFINE_SINGLETON_WEAK_REF (NMBusManager);
+NM_DEFINE_SINGLETON_REGISTER (NMBusManager);
NMBusManager *
nm_bus_manager_get (void)
@@ -103,7 +102,7 @@ nm_bus_manager_setup (NMBusManager *instance)
already_setup = TRUE;
singleton_instance = instance;
- nm_singleton_instance_weak_ref_register ();
+ nm_singleton_instance_register ();
nm_log_dbg (LOGD_CORE, "create %s singleton (%p)", "NMBusManager", singleton_instance);
}
diff --git a/src/nm-config.c b/src/nm-config.c
index aa0e05a5d8..71ff69be57 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -1671,8 +1671,7 @@ _set_config_data (NMConfig *self, NMConfigData *new_data, int signal)
g_object_unref (old_data);
}
-NM_DEFINE_SINGLETON_DESTRUCTOR (NMConfig);
-NM_DEFINE_SINGLETON_WEAK_REF (NMConfig);
+NM_DEFINE_SINGLETON_REGISTER (NMConfig);
NMConfig *
nm_config_get (void)
@@ -1688,7 +1687,7 @@ nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefix
singleton_instance = nm_config_new (cli, atomic_section_prefixes, error);
if (singleton_instance)
- nm_singleton_instance_weak_ref_register ();
+ nm_singleton_instance_register ();
return singleton_instance;
}
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 8803377a5b..6f54b22a74 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -112,7 +112,7 @@ typedef struct {
/* Singleton NMPlatform subclass instance and cached class object */
NM_DEFINE_SINGLETON_INSTANCE (NMPlatform);
-NM_DEFINE_SINGLETON_WEAK_REF (NMPlatform);
+NM_DEFINE_SINGLETON_REGISTER (NMPlatform);
/* Just always initialize a @klass instance. NM_PLATFORM_GET_CLASS()
* is only a plain read on the self instance, which the compiler
@@ -154,7 +154,7 @@ nm_platform_setup (NMPlatform *instance)
singleton_instance = instance;
- nm_singleton_instance_weak_ref_register ();
+ nm_singleton_instance_register ();
nm_log_dbg (LOGD_CORE, "setup NMPlatform singleton (%p, %s)", instance, G_OBJECT_TYPE_NAME (instance));
}