From 612d2384670378d23e46046ab42ca98d618aba43 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 18 Oct 2011 16:19:43 +0100 Subject: [PATCH] gdbus-non-socket test: avoid use of a GMainContext across a fork See https://bugzilla.gnome.org/show_bug.cgi?id=658999 for why this would be bad. Bug: https://bugzilla.gnome.org/show_bug.cgi?id=662100 Signed-off-by: Simon McVittie Reviewed-by: David Zeuthen --- gio/tests/gdbus-non-socket.c | 51 +++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/gio/tests/gdbus-non-socket.c b/gio/tests/gdbus-non-socket.c index b7417e146..4e0133843 100644 --- a/gio/tests/gdbus-non-socket.c +++ b/gio/tests/gdbus-non-socket.c @@ -204,6 +204,16 @@ static const GDBusInterfaceVTable pokee_vtable = { NULL /* set_property */ }; +/* Processes: + * + * parent + * \- first child (via fork()) is the pokee + * \- second child (via g_test_trap_fork()) is the poker + * + * The second child only exists to avoid sharing a main context between several + * second-children if we run a test resembling this one multiple times. + * See https://bugzilla.gnome.org/show_bug.cgi?id=658999 for why that's bad. + */ static void test_non_socket (void) { @@ -213,7 +223,7 @@ test_non_socket (void) GDBusConnection *connection; GError *error; gchar *guid; - pid_t child; + pid_t first_child; gint read_fd; gint write_fd; GVariant *ret; @@ -222,14 +232,20 @@ test_non_socket (void) g_assert_cmpint (pipe (in_pipes), ==, 0); g_assert_cmpint (pipe (out_pipes), ==, 0); - switch ((child = fork ())) + switch ((first_child = fork ())) { case -1: g_assert_not_reached (); break; case 0: - /* child */ + /* first child */ + + /* we shouldn't do this in the parent, because we shouldn't use a + * GMainContext both before and after fork + */ + loop = g_main_loop_new (NULL, FALSE); + read_fd = in_pipes[0]; write_fd = out_pipes[1]; g_assert_cmpint (close ( in_pipes[1]), ==, 0); /* close unused write end */ @@ -245,7 +261,7 @@ test_non_socket (void) * This is because (early) dispatching is done on the IO thread * (method_call() isn't called until we're in the right thread * though) so in rare cases the parent sends the message before - * we (the child) register the object + * we (the first child) register the object */ connection = g_dbus_connection_new_sync (stream, guid, @@ -284,7 +300,21 @@ test_non_socket (void) break; } - /* parent */ + if (!g_test_trap_fork (0, 0)) + { + /* parent */ + g_test_trap_assert_passed (); + g_assert_cmpint (kill (first_child, SIGTERM), ==, 0); + return; + } + + /* second child */ + + /* we shouldn't do this in the parent, because we shouldn't use a + * GMainContext both before and after fork + */ + loop = g_main_loop_new (NULL, FALSE); + read_fd = out_pipes[0]; write_fd = in_pipes[1]; g_assert_cmpint (close (out_pipes[1]), ==, 0); /* close unused write end */ @@ -300,7 +330,7 @@ test_non_socket (void) g_assert_no_error (error); g_object_unref (stream); - /* poke the child */ + /* poke the first child */ error = NULL; ret = g_dbus_connection_call_sync (connection, NULL, /* name */ @@ -319,8 +349,8 @@ test_non_socket (void) g_variant_unref (ret); g_object_unref (connection); - - g_assert_cmpint (kill (child, SIGTERM), ==, 0); + g_main_loop_unref (loop); + exit (0); } #else /* G_OS_UNIX */ @@ -343,14 +373,9 @@ main (int argc, g_type_init (); g_test_init (&argc, &argv, NULL); - /* all the tests rely on a shared main loop */ - loop = g_main_loop_new (NULL, FALSE); - g_test_add_func ("/gdbus/non-socket", test_non_socket); ret = g_test_run(); - g_main_loop_unref (loop); - return ret; }