mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-05 02:57:58 +02:00
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.
This commit is contained in:
parent
e0bded93f3
commit
2cf274c03e
7 changed files with 68 additions and 28 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue