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 537555 - GObject instantiation not thread safe ...
GObject instantiation not thread safe ...
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gobject
2.16.x
Other Linux
: Normal major
: ---
Assigned To: gtkdev
gtkdev
: 519387 531814 532138 534292 535257 535295 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-06-10 10:41 UTC by Michael Meeks
Modified: 2009-08-28 05:37 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
threadtests patch with test showing the problem (3.03 KB, patch)
2008-06-10 11:23 UTC, Michael Meeks
none Details | Review

Description Michael Meeks 2008-06-10 10:41:12 UTC
So - this is related to bug 64764, but different.

The basic problem is that we can do:

Foo *foo = g_object_new (foo_get_type(), "property", value, NULL);

in two threads simultaneously. Indeed we see this happen regularly (and it happes suspiciously in various crashing applications), eg. gnome-screenshot:

https://bugzilla.novell.com/show_bug.cgi?id=385128#c15

the file-selector does something like the above and provokes the issue, as you can see in the trace / output.

The essential problem is that the construction time property "property" is not initialized by the time the the second thread starts to construct the object, so we get to:

gobject.c (g_object_new_valist):

  class = g_type_class_ref (object_type);
...
      GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool,
						    name,
						    object_type,
						    TRUE);
      if (!pspec)
	{
	  g_warning ("%s: object class `%s' has no property named `%s'",
		     G_STRFUNC,
		     g_type_name (object_type),
		     name);

and give a warning:

(firefox:14234): GLib-GObject-WARNING **: IA__g_object_new_valist: object class
`GThemedIcon' has no property named `names'

which is a nonsense: and if you break here - you discover that (as the other thread runs on) - you immediately have the property as you ask for it in the debugger there :-) [ unfortunately it's a rather narrow race & hard to catch in the debugger ].
Comment 1 Michael Meeks 2008-06-10 11:23:45 UTC
Created attachment 112463 [details] [review]
threadtests patch with test showing the problem
Comment 2 Michael Meeks 2008-06-10 11:26:53 UTC
So - it seems to me that in g_type_class_ref - we really don't want to be handing out pointers to not-fully-initialized class data for a given type: it seems like rather a bad plan ;-)

gtype.c (g_type_class_ref):

  if (!node->data->class.class) /* class uninitialized */
    {
...
      g_static_rec_mutex_lock (&class_init_rec_mutex);
...
      g_static_rec_mutex_unlock (&class_init_rec_mutex);
    }
  return node->data->class.class;

should really be some typical double-check locking type pattern, but of course currently is not - the assignment to class.class occurs extremely early in this section - where it should be a very late statement (right?).
Comment 3 Tim Janik 2008-06-10 11:37:25 UTC
Thanks, applied the test with some runtime warning fixes. Please diff -up for patches next time. The test runs without problems here after recent upstream race condition fixes.

2008-06-10 13:34:01  Tim Janik  <timj@imendio.com>
        * tests/threadtests.c: added race condition tester from Michael Meeks
        with a couple fixes so it's not triggering development warnings. From:
        Bug 537555 - GObject instantiation not thread safe ...
Comment 4 Tim Janik 2008-06-10 11:39:09 UTC
(In reply to comment #2)
> So - it seems to me that in g_type_class_ref - we really don't want to be
> handing out pointers to not-fully-initialized class data for a given type: it
> seems like rather a bad plan ;-)
> 
> gtype.c (g_type_class_ref):
> 
>   if (!node->data->class.class) /* class uninitialized */
>     {
> ...
>       g_static_rec_mutex_lock (&class_init_rec_mutex);
> ...
>       g_static_rec_mutex_unlock (&class_init_rec_mutex);
>     }
>   return node->data->class.class;
> 
> should really be some typical double-check locking type pattern, but of course
> currently is not - the assignment to class.class occurs extremely early in this
> section - where it should be a very late statement (right?).

Unfortunately not, as type_class_peek and recursive _ref() needs to work on partially initialized classes. That's why we use initi_state for proper guarding in recent upstream now.
Comment 5 Morten Welinder 2008-06-10 13:42:32 UTC
*** Bug 535257 has been marked as a duplicate of this bug. ***
Comment 6 Christian Persch 2008-07-25 07:33:12 UTC
*** Bug 535295 has been marked as a duplicate of this bug. ***
Comment 7 Paolo Bacchilega 2008-08-16 10:57:05 UTC
*** Bug 546799 has been marked as a duplicate of this bug. ***
Comment 8 Milan Crha 2008-09-10 13:31:57 UTC
*** Bug 534292 has been marked as a duplicate of this bug. ***
Comment 9 Tobias Mueller 2009-01-20 00:17:00 UTC
*** Bug 519387 has been marked as a duplicate of this bug. ***
Comment 10 Akhil Laddha 2009-08-26 04:56:45 UTC
*** Bug 531814 has been marked as a duplicate of this bug. ***
Comment 11 Akhil Laddha 2009-08-28 05:37:13 UTC
*** Bug 532138 has been marked as a duplicate of this bug. ***