summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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));
}