After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 733969 - Remove atomic aspects of g_clear_pointer/object
Remove atomic aspects of g_clear_pointer/object
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gobject
unspecified
Other Windows
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2014-07-30 10:40 UTC by Alexander Larsson
Modified: 2014-09-10 17:51 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Remove atomics from g_clear_object/g_clear_pointer (3.68 KB, patch)
2014-07-30 10:41 UTC, Alexander Larsson
reviewed Details | Review
Remove atomics from g_clear_object/g_clear_pointer (4.00 KB, patch)
2014-07-30 13:11 UTC, Alexander Larsson
none Details | Review

Description Alexander Larsson 2014-07-30 10:40:36 UTC
These atomics are slow and useless (there is no way to safely use it, see patches below), so we should just remove them.
Comment 1 Alexander Larsson 2014-07-30 10:41:22 UTC
Created attachment 282012 [details] [review]
Remove atomics from g_clear_object/g_clear_pointer

Practically no caller of these functions require atomic behaviour,
but the atomics are much slower than normal operations, which makes
it desirable to get rid of them. We have not done this before because
that would be a break of the ABI.

However, I recently looked into this and it seems that even if the
atomics *are* used for g_clear_* it is not ever safe to use this.  The
atomics protects two threads that are racing to free a global/shared
object from freeing the object twice. However, any *user* of the global
object have no protection from the object being freed while in use,
because there is no paired operation the reads and refs the object
as an atomic unit (nor can such an operation be implemented using
purely atomic ops).

So, since nothing could safely have used the atomic aspects of these
functions I consider it acceptable to just remove it.
Comment 2 Allison Karlitskaya (desrt) 2014-07-30 12:41:19 UTC
Review of attachment 282012 [details] [review]:

Seems legit, but see below.

::: glib/gmem.c
@@ +218,3 @@
 
+  _p = *pp;
+  *pp = NULL;

why not make the trivial improvement of moving the assignment inside of the conditional?

::: glib/gmem.h
@@ +119,3 @@
                                                                                \
+    _p = *_pp;                                                                 \
+    *_pp = NULL;                                                               \

ditto.
Comment 3 Alexander Larsson 2014-07-30 13:11:23 UTC
Created attachment 282056 [details] [review]
Remove atomics from g_clear_object/g_clear_pointer

Practically no caller of these functions require atomic behaviour,
but the atomics are much slower than normal operations, which makes
it desirable to get rid of them. We have not done this before because
that would be a break of the ABI.

However, I recently looked into this and it seems that even if the
atomics *are* used for g_clear_* it is not ever safe to use this.  The
atomics protects two threads that are racing to free a global/shared
object from freeing the object twice. However, any *user* of the global
object have no protection from the object being freed while in use,
because there is no paired operation the reads and refs the object
as an atomic unit (nor can such an operation be implemented using
purely atomic ops).

So, since nothing could safely have used the atomic aspects of these
functions I consider it acceptable to just remove it.
Comment 4 Alexander Larsson 2014-07-30 13:22:07 UTC
Commited to master as b1dd594a22e3499caafdeccd7fa223a032b9e177
Comment 5 Xavier Claessens 2014-09-10 03:38:57 UTC
I'm unsure, can GObject::dispose() be called from 2 threads at the same time? A typical usage of g_clear_pointer/object() is to implement dispose:

dispose()
{
  g_clear_object(self->priv->foo);
}

If 2 threads runs that dispose at the same time, then the atomic was safe in that case, afaik. No?
Comment 6 Allison Karlitskaya (desrt) 2014-09-10 11:26:21 UTC
I don't think that this could reasonably happen, by extension of the same argument.

Assuming that dispose is running in two threads at the same time, it means that you were probably trying to make meaningful use of the object from two threads at the same time in which (at least) one of them may have been disposing the object.  It stands to reason that the 'other' thread would be trying to access the object that was being cleared, at which point Alex's original argument kicks in.
Comment 7 Xavier Claessens 2014-09-10 17:51:16 UTC
yeah, makes sense, indeed.