summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2011-09-13 19:56:22 -0400
committerRyan Lortie <desrt@desrt.ca>2011-09-14 14:09:07 -0400
commit01ed78d525cf2f8769022e27cc2573ec7ba123b3 (patch)
tree0073030260042fddd0938726b6d8e680b86ac23f
parent01f9479438694d0e1f4ddd738ddf046f179cbd0e (diff)
downloadglib-01ed78d525cf2f8769022e27cc2573ec7ba123b3.tar.gz
mainloop: detect fork() and abort
Abort if the child process returns to the mainloop after a fork(). https://bugzilla.gnome.org/show_bug.cgi?id=658999
-rw-r--r--glib/gmain.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/glib/gmain.c b/glib/gmain.c
index 855e63aef..aa2877ecc 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -49,6 +49,7 @@
#ifdef G_OS_UNIX
#include "glib-unix.h"
+#include <pthread.h>
#ifdef HAVE_EVENTFD
#include <sys/eventfd.h>
#endif
@@ -174,6 +175,10 @@
* <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 */
@@ -374,6 +379,7 @@ static gboolean g_idle_dispatch (GSource *source,
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;
@@ -497,6 +503,14 @@ g_main_context_unref (GMainContext *context)
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:
*
@@ -507,25 +521,27 @@ g_main_context_unref (GMainContext *context)
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_once_init_leave (&initialised, TRUE);
+ }
+
+ context = g_new0 (GMainContext, 1);
+
g_static_mutex_init (&context->mutex);
context->owner = NULL;
@@ -2976,6 +2992,7 @@ g_main_context_iterate (GMainContext *context,
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);