diff options
-rw-r--r-- | src/NetworkManagerUtils.c | 47 | ||||
-rw-r--r-- | src/NetworkManagerUtils.h | 24 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/nm-auth-manager.c | 5 | ||||
-rw-r--r-- | src/nm-bus-manager.c | 5 | ||||
-rw-r--r-- | src/nm-config.c | 5 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 4 |
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)); } |