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 300659 - most object that derivate from gobject are not thread-safe
most object that derivate from gobject are not thread-safe
Status: RESOLVED DUPLICATE of bug 65041
Product: glib
Classification: Platform
Component: gobject
2.6.x
Other All
: High critical
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2005-04-14 19:59 UTC by DINH Viet Hoa
Modified: 2005-04-14 21:34 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description DINH Viet Hoa 2005-04-14 19:59:48 UTC
Steps to reproduce:
most data types that derivate from g_object are implemented this way :

static GType foo_get_type (void)
{
  static GType iface_type = 0;
  
  if (!iface_type) {
      /* block (1) */
      static const GTypeInfo iface_info = { ... };
      
      iface_type = g_type_register_static (G_TYPE_INTERFACE,
					    "foo",
					    &iface_info, 0);
  }
  return iface_type;						
}

creation of the object is called with :

g_object_new(foo_get_type())

that means that if two objects are created at the same time,
in two different threads, they can enter both in the block (1),
so that, they will both call g_type_register_static() and an assert()
can raise when this function is called twice for the same object.

using testcommon.h in the example of glib / gobject, I wrote the following :

#include <pthread.h>
#include <string.h>
#include <glib-object.h>
#include "testcommon.h"
#include <stdio.h>
#include <gtk/gtk.h>

/*
 * TestObject, a parent class for TestObject
 */
#define TEST_TYPE_OBJECT          (test_object_get_type ())
typedef struct _TestObject        TestObject;
typedef struct _TestObjectClass   TestObjectClass;

struct _TestObject
{
  GObject parent_instance;
};
struct _TestObjectClass
{
  GObjectClass parent_class;
};

static GType test_object_get_type (void);

static void
test_object_class_init (TestObjectClass *class)
{
}

static DEFINE_TYPE(TestObject, test_object,
		   test_object_class_init, NULL, NULL,
		   G_TYPE_OBJECT)

static void * thread(void * data)
{
  unsigned int i;
  
  for(i = 0 ; i < 10000 ; i ++) {
    TestObject *object;
    
    object = g_object_newv (TEST_TYPE_OBJECT, 0, NULL);
    g_object_unref(object);
  }
  
  return NULL;
}

#define NUM 5

int main(int argc, char *argv[])
{
  pthread_t thread_id[NUM];
  unsigned int i;
  
  g_thread_init(NULL);
  g_type_init();
  
  for(i = 0 ; i < NUM ; i ++)
    pthread_create(&thread_id[i], NULL, thread, NULL);
  thread(NULL);
  
  for(i = 0 ; i < NUM ; i++)
    pthread_join(thread_id[i], NULL);
  
  return 0;
}

of course, if I simply allocate and deallocate a GtkWindow or a GtkTreeStore,
it will also crash.


Stack trace:
I can see :

GLib-GObject-ERROR **: g_type_plugin_*() invalidly modified type `TestObject'
aborting...
Aborted (core dumped)

or :

Segmentation fault (core dumped)


Other information:
I can workaround the problem by locking whenever I want to allocate a given
type of object.
Comment 1 Manish Singh 2005-04-14 21:34:32 UTC
Next time, please search for duplicates before filing bugs.

*** This bug has been marked as a duplicate of 65041 ***