Index: glib/gmain.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gmain.c,v
retrieving revision 1.146
diff -u -3 -p -r1.146 gmain.c
--- glib/gmain.c	16 Aug 2006 03:33:56 -0000	1.146
+++ glib/gmain.c	6 Sep 2006 16:59:31 -0000
@@ -147,7 +147,7 @@ struct _GMainContext
 #endif /* G_OS_WIN32 */
 
   GPollFD wake_up_rec;
-  gboolean poll_waiting;
+  gint poll_waiting; /* atomic */
 
 /* Flag indicating whether the set of fd's changed during a poll */
   gboolean poll_changed;
@@ -242,7 +242,6 @@ static void g_main_context_add_poll_unlo
 						 GPollFD      *fd);
 static void g_main_context_remove_poll_unlocked (GMainContext *context,
 						 GPollFD      *fd);
-static void g_main_context_wakeup_unlocked      (GMainContext *context);
 
 static gboolean g_timeout_prepare  (GSource     *source,
 				    gint        *timeout);
@@ -921,7 +920,7 @@ g_source_attach (GSource      *source,
 
 #ifdef G_THREADS_ENABLED
   /* Now wake up the main loop if it is waiting in the poll() */
-  g_main_context_wakeup_unlocked (context);
+  g_main_context_wakeup (context);
 #endif
 
   UNLOCK_CONTEXT (context);
@@ -2303,14 +2302,12 @@ g_main_context_prepare (GMainContext *co
     }
 
 #ifdef G_THREADS_ENABLED
-  if (context->poll_waiting)
+  if (!g_atomic_int_compare_and_exchange (&context->poll_waiting, 0, 1))
     {
       g_warning("g_main_context_prepare(): main loop already active in another thread");
       UNLOCK_CONTEXT (context);
       return FALSE;
     }
-  
-  context->poll_waiting = TRUE;
 #endif /* G_THREADS_ENABLED */
 
 #if 0
@@ -2496,15 +2493,13 @@ g_main_context_check (GMainContext *cont
     }
   
 #ifdef G_THREADS_ENABLED
-  if (!context->poll_waiting)
+  if (!g_atomic_int_compare_and_exchange (&context->poll_waiting, 1, 0))
     {
 #ifndef G_OS_WIN32
       gchar a;
       read (context->wake_up_pipe[0], &a, 1);
 #endif
     }
-  else
-    context->poll_waiting = FALSE;
 
   /* If the set of poll file descriptors changed, bail out
    * and let the main loop rerun
@@ -2904,7 +2899,7 @@ g_main_loop_quit (GMainLoop *loop)
 
   LOCK_CONTEXT (loop->context);
   loop->is_running = FALSE;
-  g_main_context_wakeup_unlocked (loop->context);
+  g_main_context_wakeup (loop->context);
 
 #ifdef G_THREADS_ENABLED
   if (loop->context->cond)
@@ -3092,7 +3087,7 @@ g_main_context_add_poll_unlocked (GMainC
   context->poll_changed = TRUE;
 
   /* Now wake up the main loop if it is waiting in the poll() */
-  g_main_context_wakeup_unlocked (context);
+  g_main_context_wakeup (context);
 #endif
 }
 
@@ -3150,7 +3145,7 @@ g_main_context_remove_poll_unlocked (GMa
   context->poll_changed = TRUE;
   
   /* Now wake up the main loop if it is waiting in the poll() */
-  g_main_context_wakeup_unlocked (context);
+  g_main_context_wakeup (context);
 #endif
 }
 
@@ -3251,30 +3246,14 @@ g_main_context_get_poll_func (GMainConte
   return result;
 }
 
-/* HOLDS: context's lock */
-/* Wake the main loop up from a poll() */
-static void
-g_main_context_wakeup_unlocked (GMainContext *context)
-{
-#ifdef G_THREADS_ENABLED
-  if (g_thread_supported() && context->poll_waiting)
-    {
-      context->poll_waiting = FALSE;
-#ifndef G_OS_WIN32
-      write (context->wake_up_pipe[1], "A", 1);
-#else
-      ReleaseSemaphore (context->wake_up_semaphore, 1, NULL);
-#endif
-    }
-#endif
-}
-
 /**
  * g_main_context_wakeup:
  * @context: a #GMainContext
  * 
  * If @context is currently waiting in a poll(), interrupt
- * the poll(), and continue the iteration process.
+ * the poll(), and continue the iteration process. 
+ * <note>This function is async safe, so it can be called
+ * from within a UNIX signal handler.</note>
  **/
 void
 g_main_context_wakeup (GMainContext *context)
@@ -3284,9 +3263,17 @@ g_main_context_wakeup (GMainContext *con
   
   g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
 
-  LOCK_CONTEXT (context);
-  g_main_context_wakeup_unlocked (context);
-  UNLOCK_CONTEXT (context);
+#ifdef G_THREADS_ENABLED
+  if (g_thread_supported() && 
+      g_atomic_int_compare_and_exchange (&context->poll_waiting, 1, 0))
+    {
+#ifndef G_OS_WIN32
+      write (context->wake_up_pipe[1], "A", 1);
+#else
+      ReleaseSemaphore (context->wake_up_semaphore, 1, NULL);
+#endif
+    }
+#endif
 }
 
 /**
