mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-09 15:50:26 +01:00
shared: fix race in nm_ref_string_unref()
We cannot drop the reference count to zero while having
no lock. Otherwise, another thread might race doing
s = nm_ref_string_new("...");
nm_ref_string_unref(s);
and already successfully delete the instance.
Hitting this race should be rather difficult, especially because
we tend to use NMRefString only from one thread. But still, access
to global variables must be race free.
Fixes: 908fadec96 ('shared: add NMRefString')
This commit is contained in:
parent
ef6edd8dbd
commit
3490a09a7d
1 changed files with 9 additions and 8 deletions
|
|
@ -168,24 +168,25 @@ void
|
|||
_nm_ref_string_unref_non_null(NMRefString *rstr)
|
||||
{
|
||||
RefString *const rstr0 = (RefString *) rstr;
|
||||
int r;
|
||||
|
||||
_ASSERT(rstr0);
|
||||
|
||||
if (G_LIKELY(!g_atomic_int_dec_and_test(&rstr0->ref_count)))
|
||||
/* fast-path: first try to decrement the ref-count without bringing it
|
||||
* to zero. */
|
||||
r = rstr0->ref_count;
|
||||
if (G_LIKELY(r > 1 && g_atomic_int_compare_and_exchange(&rstr0->ref_count, r, r - 1)))
|
||||
return;
|
||||
|
||||
/* We apparently are about to return the last reference. Take a lock. */
|
||||
|
||||
G_LOCK(gl_lock);
|
||||
|
||||
/* in the fast-path above, we already decremented the ref-count to zero.
|
||||
* We need recheck that the ref-count is still zero. */
|
||||
nm_assert(g_hash_table_lookup(gl_hash, rstr0) == rstr0);
|
||||
|
||||
if (g_atomic_int_get(&rstr0->ref_count) == 0) {
|
||||
if (G_LIKELY(g_atomic_int_dec_and_test(&rstr0->ref_count))) {
|
||||
if (!g_hash_table_remove(gl_hash, rstr0))
|
||||
nm_assert_not_reached();
|
||||
} else {
|
||||
#if NM_MORE_ASSERTS > 5
|
||||
nm_assert(g_hash_table_lookup(gl_hash, rstr0) == rstr0);
|
||||
#endif
|
||||
}
|
||||
|
||||
G_UNLOCK(gl_lock);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue