Subject: bug#36609: 27.0.50; Possible race-condition in threading implementation

From: Eli Zaretskii <[email-masked]>
Date: Sun, 20 Jun 2021 14:39:31 +0300

> From: [email-masked]
> Cc: [email-masked]
> Date: Sat, 19 Jun 2021 17:12:32 -0400
> 
> "Suggest" or "Provide"?
> 
> If the former, well, my recalcitrance should be your answer.
> 
> If the latter, sure

Thanks, please try the patch below.

> although if you've written the patch, then running my MREs would be
> epsilon more effort.

You have a use case and wrote code with which you are familiar, so you
are in a better position to test it.  Moreover, I don't have access to
a system where these problems could happen, so it's far from epsilon
effort for me.

diff --git a/src/xgselect.c b/src/xgselect.c
index 0d91d55bad..9a90670b0f 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -34,12 +34,27 @@ static GMainContext *glib_main_context;
 
 void release_select_lock (void)
 {
+#if GNUC_PREREQ (4, 7, 0)
+  if (__atomic_sub_fetch (&threads_holding_glib_lock, 1, __ATOMIC_ACQ_REL))
+    g_main_context_release (glib_main_context);
+#else
   if (--threads_holding_glib_lock == 0)
     g_main_context_release (glib_main_context);
+#endif
 }
 
 static void acquire_select_lock (GMainContext *context)
 {
+#if GNUC_PREREQ (4, 7, 0)
+  if (__atomic_fetch_add (&threads_holding_glib_lock, 1, __ATOMIC_ACQ_REL) == 0)
+    {
+      glib_main_context = context;
+      while (!g_main_context_acquire (context))
+	{
+	  /* Spin. */
+	}
+    }
+#else
   if (threads_holding_glib_lock++ == 0)
     {
       glib_main_context = context;
@@ -48,6 +63,7 @@ static void acquire_select_lock (GMainContext *context)
 	  /* Spin. */
 	}
     }
+#endif
 }
 
 /* `xg_select' is a `pselect' replacement.  Why do we need a separate function?