libnm: make _nm_register_setting() thread safe
_nm_register_setting() and _nm_register_setting_impl() are called from within the GType constructor for the NMSetting subtype. As such, at that point it runs inside a g_once_init_enter() block. However, each implementation for initializing the GType has a separate g_once_init_enter() variable, hence, if two threads create GType instances for different NMSetting subclasses, there is a race. libnm is not thread safe. However, it should be at least thread safe with respect to constructing the GType instances.
This commit is contained in:
@@ -123,12 +123,16 @@ _register_settings_init (void)
|
|||||||
* @priority: the sort priority of the setting, see #NMSettingPriority
|
* @priority: the sort priority of the setting, see #NMSettingPriority
|
||||||
*
|
*
|
||||||
* INTERNAL ONLY: registers a setting's internal properties with libnm.
|
* INTERNAL ONLY: registers a setting's internal properties with libnm.
|
||||||
|
*
|
||||||
|
* This should be called from within G_DEFINE_TYPE_WITH_CODE() when initializing
|
||||||
|
* the setting type.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_nm_register_setting_impl (const char *name,
|
_nm_register_setting_impl (const char *name,
|
||||||
GType type,
|
GType type,
|
||||||
NMSettingPriority priority)
|
NMSettingPriority priority)
|
||||||
{
|
{
|
||||||
|
static GMutex mutex;
|
||||||
SettingInfo *info;
|
SettingInfo *info;
|
||||||
|
|
||||||
nm_assert (name && *name);
|
nm_assert (name && *name);
|
||||||
@@ -137,9 +141,6 @@ _nm_register_setting_impl (const char *name,
|
|||||||
|
|
||||||
_register_settings_ensure_inited ();
|
_register_settings_ensure_inited ();
|
||||||
|
|
||||||
nm_assert (!g_hash_table_lookup (registered_settings, name));
|
|
||||||
nm_assert (!g_hash_table_lookup (registered_settings_by_type, &type));
|
|
||||||
|
|
||||||
nm_assert ( priority != NM_SETTING_PRIORITY_CONNECTION
|
nm_assert ( priority != NM_SETTING_PRIORITY_CONNECTION
|
||||||
|| nm_streq (name, NM_SETTING_CONNECTION_SETTING_NAME));
|
|| nm_streq (name, NM_SETTING_CONNECTION_SETTING_NAME));
|
||||||
|
|
||||||
@@ -147,8 +148,16 @@ _nm_register_setting_impl (const char *name,
|
|||||||
info->type = type;
|
info->type = type;
|
||||||
info->priority = priority;
|
info->priority = priority;
|
||||||
info->name = name;
|
info->name = name;
|
||||||
|
|
||||||
|
g_mutex_lock (&mutex);
|
||||||
|
nm_assert (registered_settings);
|
||||||
|
nm_assert (registered_settings_by_type);
|
||||||
|
nm_assert (!g_hash_table_contains (registered_settings, name));
|
||||||
|
nm_assert (!g_hash_table_contains (registered_settings_by_type, &type));
|
||||||
|
|
||||||
g_hash_table_insert (registered_settings, (void *) info->name, info);
|
g_hash_table_insert (registered_settings, (void *) info->name, info);
|
||||||
g_hash_table_insert (registered_settings_by_type, &info->type, info);
|
g_hash_table_insert (registered_settings_by_type, &info->type, info);
|
||||||
|
g_mutex_unlock (&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const SettingInfo *
|
static const SettingInfo *
|
||||||
|
Reference in New Issue
Block a user