glib/gobject
Thomas Haller 9ae43169cf gobject: fix race in toggle ref during g_object_ref()
Previously:

   1. old_val = atomic_add(&object->ref_count);
   2. if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object)) { toggle_notify() }

As old_val was 1, you might think that no other thread can have a valid
reference to object. However, that's not the case. For one, GWeakRef can
be used to create another strong reference. More easily, the single
reference can be shared between multiple threads (as long as the code
takes care that the object lives long enough).

That means, another thread can easily add and drop references (including
toggle references). All between step 1 and 2.

A race here might be hard to hit, and the effect might not be obviously
bad. However, consider old_val is 1 due to a normal reference, and
another thread adds a toggle ref between step 1. and 2. Then we would
notify a toggle from 1->2, although a newly added toggle ref is expected
to always start with a normal and a toggle reference. The first toggle
notification is expected to notify about the loss of other references, not
about getting a second reference.

To handle this properly, when we increase the reference count from 1 to
2, we must do so under a lock and check for the toggle notification.

As we now correctly track the toggle behavior, we can also assert in
toggle_refs_get_notify_unlocked() that n_toggle_refs agrees with the
number of references, that is, that the user did always match
g_object_add_toggle_ref() with g_object_remove_toggle_ref().

The downside is here too, that there is now a case (when increasing the
reference count from 1 to 2)  where we need to take the global lock.
That performance problem should be addresses by using per-object locks
instead of a global lock.
2023-12-28 09:36:56 +01:00
..
2023-10-16 23:34:04 +01:00
2022-10-13 20:53:56 -04:00
2023-10-16 23:35:05 +01:00
2022-10-13 20:53:56 -04:00
2022-10-13 20:53:56 -04:00
2023-10-16 23:34:24 +01:00
2023-12-19 18:41:02 +00:00
2023-12-19 18:41:02 +00:00
2022-10-13 20:53:56 -04:00
2022-10-13 20:53:56 -04:00
2023-10-23 11:26:53 +01:00
2022-10-13 20:53:56 -04:00
2023-10-23 11:26:53 +01:00