}
static void
-dispatch_unix_signals (void)
+dispatch_unix_signals_unlocked (void)
{
+ gboolean pending[NSIG];
GSList *node;
+ gint i;
/* clear this first incase another one arrives while we're processing */
any_unix_signal_pending = FALSE;
- G_LOCK(unix_signal_lock);
+ /* We atomically test/clear the bit from the global array in case
+ * other signals arrive while we are dispatching.
+ *
+ * We then can safely use our own array below without worrying about
+ * races.
+ */
+ for (i = 0; i < NSIG; i++)
+ pending[i] = g_atomic_int_compare_and_exchange (&unix_signal_pending[i], TRUE, FALSE);
/* handle GChildWatchSource instances */
- if (unix_signal_pending[SIGCHLD])
+ if (pending[SIGCHLD])
{
/* The only way we can do this is to scan all of the children.
*
if (!source->pending)
{
- if (unix_signal_pending[source->signum])
+ if (pending[source->signum])
{
source->pending = TRUE;
}
}
- memset ((void*)unix_signal_pending, 0, sizeof (unix_signal_pending));
+}
+static void
+dispatch_unix_signals (void)
+{
+ G_LOCK(unix_signal_lock);
+ dispatch_unix_signals_unlocked ();
G_UNLOCK(unix_signal_lock);
}
G_LOCK (unix_signal_lock);
ref_unix_signal_handler_unlocked (signum);
unix_signal_watches = g_slist_prepend (unix_signal_watches, unix_signal_source);
- if (unix_signal_pending[signum])
- unix_signal_source->pending = TRUE;
+ dispatch_unix_signals_unlocked ();
G_UNLOCK (unix_signal_lock);
return source;