#ifdef G_OS_UNIX
#include "glib-unix.h"
+#include <pthread.h>
#ifdef HAVE_EVENTFD
#include <sys/eventfd.h>
#endif
* <graphic fileref="mainloop-states.gif" format="GIF"></graphic>
* </figure>
* </refsect2>
+ *
+ * On Unix, the GLib mainloop is incompatible with fork(). Any program
+ * using the mainloop must either exec() or exit() from the child
+ * without returning to the mainloop.
*/
/* Types */
/* The following lock is used for both the list of sources
* and the list of poll records
*/
- GStaticMutex mutex;
+ GMutex mutex;
GCond *cond;
GThread *owner;
guint owner_count;
GSource *parent_source;
};
-#define LOCK_CONTEXT(context) g_static_mutex_lock (&context->mutex)
-#define UNLOCK_CONTEXT(context) g_static_mutex_unlock (&context->mutex)
+#define LOCK_CONTEXT(context) g_mutex_lock (&context->mutex)
+#define UNLOCK_CONTEXT(context) g_mutex_unlock (&context->mutex)
#define G_THREAD_SELF g_thread_self ()
#define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0)
gpointer user_data);
static GMainContext *glib_worker_context;
+static gboolean g_main_context_fork_detected;
G_LOCK_DEFINE_STATIC (main_loop);
static GMainContext *default_main_context;
source = next;
}
- g_static_mutex_free (&context->mutex);
+ g_mutex_clear (&context->mutex);
g_ptr_array_free (context->pending_dispatches, TRUE);
g_free (context->cached_poll_array);
g_free (context);
}
+#ifdef G_OS_UNIX
+static void
+g_main_context_forked (void)
+{
+ g_main_context_fork_detected = TRUE;
+}
+#endif
+
/**
* g_main_context_new:
*
GMainContext *
g_main_context_new (void)
{
+ static gsize initialised;
GMainContext *context;
g_thread_init_glib ();
- context = g_new0 (GMainContext, 1);
-
+ if (g_once_init_enter (&initialised))
+ {
#ifdef G_MAIN_POLL_DEBUG
- {
- static gboolean beenhere = FALSE;
+ if (getenv ("G_MAIN_POLL_DEBUG") != NULL)
+ _g_main_poll_debug = TRUE;
+#endif
- if (!beenhere)
- {
- if (getenv ("G_MAIN_POLL_DEBUG") != NULL)
- _g_main_poll_debug = TRUE;
- beenhere = TRUE;
- }
- }
+#ifdef G_OS_UNIX
+ pthread_atfork (NULL, NULL, g_main_context_forked);
#endif
- g_static_mutex_init (&context->mutex);
+ g_once_init_leave (&initialised, TRUE);
+ }
+
+ context = g_new0 (GMainContext, 1);
+
+ g_mutex_init (&context->mutex);
context->owner = NULL;
context->waiters = NULL;
if (context->waiters)
{
GMainWaiter *waiter = context->waiters->data;
- gboolean loop_internal_waiter =
- (waiter->mutex == g_static_mutex_get_mutex (&context->mutex));
+ gboolean loop_internal_waiter = (waiter->mutex == &context->mutex);
context->waiters = g_slist_delete_link (context->waiters,
context->waiters);
if (!loop_internal_waiter)
if (context == NULL)
context = g_main_context_default ();
- loop_internal_waiter = (mutex == g_static_mutex_get_mutex (&context->mutex));
+ loop_internal_waiter = (mutex == &context->mutex);
if (!loop_internal_waiter)
LOCK_CONTEXT (context);
got_ownership = g_main_context_wait (context,
context->cond,
- g_static_mutex_get_mutex (&context->mutex));
+ &context->mutex);
if (!got_ownership)
return FALSE;
if (!block)
timeout = 0;
+ g_assert (!g_main_context_fork_detected);
g_main_context_poll (context, timeout, max_priority, fds, nfds);
some_ready = g_main_context_check (context, max_priority, fds, nfds);
while (loop->is_running && !got_ownership)
got_ownership = g_main_context_wait (loop->context,
loop->context->cond,
- g_static_mutex_get_mutex (&loop->context->mutex));
+ &loop->context->mutex);
if (!loop->is_running)
{
return FALSE;
}
-
static gboolean
g_child_watch_check (GSource *source)
{
return child_exited;
}
+static void
+g_child_watch_finalize (GSource *source)
+{
+}
+
#else /* G_OS_WIN32 */
static void
return source;
}
-static void
+static void
g_unix_signal_watch_finalize (GSource *source)
{
G_LOCK (unix_signal_lock);
G_UNLOCK (unix_signal_lock);
}
-#endif /* G_OS_WIN32 */
-
static void
g_child_watch_finalize (GSource *source)
{
G_UNLOCK (unix_signal_lock);
}
+#endif /* G_OS_WIN32 */
+
static gboolean
g_child_watch_dispatch (GSource *source,
GSourceFunc callback,
{
g_main_context_iteration (glib_worker_context, TRUE);
+#ifdef G_OS_UNIX
if (any_unix_signal_pending)
dispatch_unix_signals ();
+#endif
}
return NULL; /* worst GCC warning message ever... */
GError *error = NULL;
glib_worker_context = g_main_context_new ();
- if (g_thread_create (glib_worker_main, NULL, FALSE, &error) == NULL)
+ if (g_thread_new ("gmain", glib_worker_main, NULL, FALSE, &error) == NULL)
g_error ("Creating GLib worker thread failed: %s\n", error->message);
g_once_init_leave (&initialised, TRUE);