diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c index f9ead9e49..fc5d4624e 100644 --- a/gio/tests/gsubprocess.c +++ b/gio/tests/gsubprocess.c @@ -1819,7 +1819,8 @@ test_pass_fd_inherit_fds (void) static void do_test_fd_conflation (GSubprocessFlags flags, - GSpawnChildSetupFunc child_setup) + GSpawnChildSetupFunc child_setup, + gboolean test_child_err_report_fd) { char success_message[] = "Yay success!"; GError *error = NULL; @@ -1829,6 +1830,7 @@ do_test_fd_conflation (GSubprocessFlags flags, GPtrArray *args; int unused_pipefds[2]; int pipefds[2]; + int fd_to_pass_to_child; gsize bytes_written; gboolean success; char *fd_str; @@ -1881,18 +1883,26 @@ do_test_fd_conflation (GSubprocessFlags flags, * fds. The primary goal of this test is to ensure this particular conflation * issue is not reintroduced. See glib#2503. * + * This test also has an alternate mode of operation where it instead tests + * for conflation with gspawn's child_err_report_fd, glib#2506. + * * Be aware this test is necessarily extremely fragile. To reproduce these * bugs, it relies on internals of gspawn and gmain that will likely change * in the future, eventually causing this test to no longer test the bugs * it was originally designed to test. That is OK! If the test fails, at * least you know *something* is wrong. */ + if (test_child_err_report_fd) + fd_to_pass_to_child = pipefds[1] + 2 /* 8 */; + else + fd_to_pass_to_child = pipefds[1] + 3 /* 9 */; + launcher = g_subprocess_launcher_new (flags); - g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, pipefds[1] + 3 /* 9 */); + g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, fd_to_pass_to_child); g_subprocess_launcher_take_fd (launcher, unused_pipefds[0] /* 3 */, pipefds[1] + 1 /* 7 */); if (child_setup != NULL) g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL); - fd_str = g_strdup_printf ("%d", pipefds[1] + 3); + fd_str = g_strdup_printf ("%d", fd_to_pass_to_child); args = get_test_subprocess_args ("read-from-fd", fd_str, NULL); proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, &error); g_assert_no_error (error); @@ -1908,12 +1918,20 @@ do_test_fd_conflation (GSubprocessFlags flags, /* Also close the write end of the unused pipe. */ close (unused_pipefds[1]); - /* So now pipefds[0] should be inherited into the subprocess as + /* If doing our normal test: + * + * So now pipefds[0] should be inherited into the subprocess as * pipefds[1] + 2, and unused_pipefds[0] should be inherited as * pipefds[1] + 1. We will write to pipefds[1] and the subprocess will verify * that it reads the expected data. But older broken GIO will accidentally * clobber pipefds[1] + 2 with pipefds[1] + 1! This will cause the subprocess * to hang trying to read from the wrong pipe. + * + * If testing conflation with child_err_report_fd: + * + * We are actually already done. The real test succeeded if we made it this + * far without hanging while spawning the child. But let's continue with our + * write and read anyway, to ensure things are good. */ output_stream = g_unix_output_stream_new (pipefds[1], TRUE); success = g_output_stream_write_all (output_stream, @@ -1934,7 +1952,7 @@ do_test_fd_conflation (GSubprocessFlags flags, static void test_fd_conflation (void) { - do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL); + do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL, FALSE); } static void @@ -1943,7 +1961,7 @@ test_fd_conflation_empty_child_setup (void) /* Using a child setup function forces gspawn to use fork/exec * rather than posix_spawn. */ - do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup); + do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, FALSE); } static void @@ -1954,7 +1972,16 @@ test_fd_conflation_inherit_fds (void) * posix_spawn codepath does not currently handle closing * non-inherited fds. */ - do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL); + do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL, FALSE); +} + +static void +test_fd_conflation_child_err_report_fd (void) +{ + /* Using a child setup function forces gspawn to use fork/exec + * rather than posix_spawn. + */ + do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, TRUE); } #endif @@ -2100,6 +2127,7 @@ main (int argc, char **argv) g_test_add_func ("/gsubprocess/fd-conflation/basic", test_fd_conflation); g_test_add_func ("/gsubprocess/fd-conflation/empty-child-setup", test_fd_conflation_empty_child_setup); g_test_add_func ("/gsubprocess/fd-conflation/inherit-fds", test_fd_conflation_inherit_fds); + g_test_add_func ("/gsubprocess/fd-conflation/child-err-report-fd", test_fd_conflation_child_err_report_fd); #endif g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);