Add ensure_required_types constructor 53/316453/1
authorMichal Bloch <m.bloch@samsung.com>
Wed, 21 Aug 2024 16:46:04 +0000 (18:46 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Wed, 21 Aug 2024 17:54:43 +0000 (19:54 +0200)
Attempt to work around a deadlock bug.

Change-Id: Ic9d46c0d0946738b19070eb3c22f61dc7c8f80ca

gio/gdbusprivate.c

index 2c9238c..f5cebcb 100644 (file)
@@ -238,8 +238,10 @@ release_required_types (void)
 static void
 ensure_required_types (void)
 {
-  g_assert (ensured_classes == NULL);
+  if (ensured_classes != NULL)
+    return;
   ensured_classes = g_ptr_array_new ();
+
   /* Generally in this list, you should initialize types which are used as
    * properties first, then the class which has them. For example, GDBusProxy
    * has a type of GDBusConnection, so we initialize GDBusConnection first.
@@ -289,6 +291,18 @@ gdbus_shared_thread_func (gpointer user_data)
   return NULL;
 }
 
+/* See `ensure_required_types` for rationale. Doing this in a library constructor
+ * is to ensure extra hard that it happens before there are any extra threads that
+ * could produce a deadlock. */
+static void __attribute__ ((constructor)) ensure_required_types_constructor (void)
+{
+       /* No thread safety (e.g. `g_init_once`) should be needed, as
+        * constructors run at library load, before other threads can use
+        * the library or even before other threads are even spawned. */
+       g_assert (ensured_classes == NULL);
+       ensure_required_types();
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 static SharedThreadData *