l3cfg: make nm_l3_config_data_cmp_full() thread-safe

Let's not have unexpected, non-thread-safe functions somewhere deep down.

NML3ConfigData -- as a data structure -- is not thread-safe, nor aims it to
be. However, our code(!) should be thread-safe. That means, it should be
possible to call our code on separate data from multiple threads.
Violating that is a code smell and a foot gun.

This basically means that code should not access global data (unless
thread-local) or that the access to global-data needs to be
synchronized.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1806
This commit is contained in:
Thomas Haller
2022-12-16 18:11:33 +01:00
parent 5a6c8c9ba4
commit 7d0b643e9f

View File

@@ -2231,14 +2231,23 @@ static const NML3ConfigData *
get_empty_l3cd(void) get_empty_l3cd(void)
{ {
static NML3ConfigData *empty_l3cd; static NML3ConfigData *empty_l3cd;
NML3ConfigData *l3cd;
if (!empty_l3cd) { again:
empty_l3cd = l3cd = g_atomic_pointer_get(&empty_l3cd);
nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN); if (G_UNLIKELY(!l3cd)) {
empty_l3cd->ifindex = 0; l3cd = nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN);
l3cd->ifindex = 0;
nm_l3_config_data_seal(l3cd);
if (!g_atomic_pointer_compare_and_exchange(&empty_l3cd, NULL, l3cd)) {
nm_l3_config_data_unref(l3cd);
goto again;
}
} }
return empty_l3cd; return l3cd;
} }
int int