gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / gio / tests / gsubprocess.c
1 #include <gio/gio.h>
2 #include <string.h>
3
4 #ifdef G_OS_UNIX
5 #include <sys/wait.h>
6 #include <glib-unix.h>
7 #include <gio/gunixinputstream.h>
8 #include <gio/gunixoutputstream.h>
9 #include <gio/gfiledescriptorbased.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #endif
13
14 #ifdef __linux__
15 #include <sys/ptrace.h>
16 #endif
17
18 /* We write 2^1 + 2^2 ... + 2^10 or 2047 copies of "Hello World!\n"
19  * ultimately
20  */
21 #define TOTAL_HELLOS 2047
22 #define HELLO_WORLD "hello world!\n"
23
24 #ifdef G_OS_WIN32
25 #define LINEEND "\r\n"
26 #define EXEEXT ".exe"
27 #define SPLICELEN (TOTAL_HELLOS * (strlen (HELLO_WORLD) + 1)) /* because \r */
28 #else
29 #define LINEEND "\n"
30 #define EXEEXT
31 #define SPLICELEN (TOTAL_HELLOS * strlen (HELLO_WORLD))
32 #endif
33
34
35
36 #ifdef G_OS_WIN32
37 #define TESTPROG "gsubprocess-testprog.exe"
38 #else
39 #define TESTPROG "gsubprocess-testprog"
40 #endif
41
42 static GPtrArray *
43 get_test_subprocess_args (const char *mode,
44                           ...) G_GNUC_NULL_TERMINATED;
45
46 static GPtrArray *
47 get_test_subprocess_args (const char *mode,
48                           ...)
49 {
50   GPtrArray *ret;
51   char *path;
52   va_list args;
53   gpointer arg;
54
55   ret = g_ptr_array_new_with_free_func (g_free);
56
57   path = g_test_build_filename (G_TEST_BUILT, TESTPROG, NULL);
58   g_ptr_array_add (ret, path);
59   g_ptr_array_add (ret, g_strdup (mode));
60
61   va_start (args, mode);
62   while ((arg = va_arg (args, gpointer)) != NULL)
63     g_ptr_array_add (ret, g_strdup (arg));
64   va_end (args);
65
66   g_ptr_array_add (ret, NULL);
67   return ret;
68 }
69
70 static void
71 test_noop (void)
72 {
73   GError *local_error = NULL;
74   GError **error = &local_error;
75   GPtrArray *args;
76   GSubprocess *proc;
77
78   args = get_test_subprocess_args ("noop", NULL);
79   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
80   g_ptr_array_free (args, TRUE);
81   g_assert_no_error (local_error);
82
83   g_subprocess_wait_check (proc, NULL, error);
84   g_assert_no_error (local_error);
85   g_assert_true (g_subprocess_get_successful (proc));
86
87   g_object_unref (proc);
88 }
89
90 static void
91 check_ready (GObject      *source,
92              GAsyncResult *res,
93              gpointer      user_data)
94 {
95   gboolean ret;
96   GError *error = NULL;
97
98   ret = g_subprocess_wait_check_finish (G_SUBPROCESS (source),
99                                         res,
100                                         &error);
101   g_assert_true (ret);
102   g_assert_no_error (error);
103
104   g_object_unref (source);
105 }
106
107 static void
108 test_noop_all_to_null (void)
109 {
110   GError *local_error = NULL;
111   GError **error = &local_error;
112   GPtrArray *args;
113   GSubprocess *proc;
114
115   args = get_test_subprocess_args ("noop", NULL);
116   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
117                             G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_SILENCE,
118                             error);
119   g_ptr_array_free (args, TRUE);
120   g_assert_no_error (local_error);
121
122   g_subprocess_wait_check_async (proc, NULL, check_ready, NULL);
123 }
124
125 static void
126 test_noop_no_wait (void)
127 {
128   GError *local_error = NULL;
129   GError **error = &local_error;
130   GPtrArray *args;
131   GSubprocess *proc;
132
133   args = get_test_subprocess_args ("noop", NULL);
134   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
135   g_ptr_array_free (args, TRUE);
136   g_assert_no_error (local_error);
137
138   g_object_unref (proc);
139 }
140
141 static void
142 test_noop_stdin_inherit (void)
143 {
144   GError *local_error = NULL;
145   GError **error = &local_error;
146   GPtrArray *args;
147   GSubprocess *proc;
148
149   args = get_test_subprocess_args ("noop", NULL);
150   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDIN_INHERIT, error);
151   g_ptr_array_free (args, TRUE);
152   g_assert_no_error (local_error);
153
154   g_subprocess_wait_check (proc, NULL, error);
155   g_assert_no_error (local_error);
156
157   g_object_unref (proc);
158 }
159
160 #ifdef G_OS_UNIX
161 static void
162 test_search_path (void)
163 {
164   GError *local_error = NULL;
165   GError **error = &local_error;
166   GSubprocess *proc;
167
168   proc = g_subprocess_new (G_SUBPROCESS_FLAGS_NONE, error, "true", NULL);
169   g_assert_no_error (local_error);
170
171   g_subprocess_wait_check (proc, NULL, error);
172   g_assert_no_error (local_error);
173
174   g_object_unref (proc);
175 }
176
177 static void
178 test_search_path_from_envp (void)
179 {
180   GError *local_error = NULL;
181   GError **error = &local_error;
182   GSubprocessLauncher *launcher;
183   GSubprocess *proc;
184   const char *path;
185
186   path = g_test_get_dir (G_TEST_BUILT);
187
188   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP);
189   g_subprocess_launcher_setenv (launcher, "PATH", path, TRUE);
190
191   proc = g_subprocess_launcher_spawn (launcher, error, TESTPROG, "exit1", NULL);
192   g_assert_no_error (local_error);
193   g_object_unref (launcher);
194
195   g_subprocess_wait_check (proc, NULL, error);
196   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
197   g_clear_error (error);
198
199   g_object_unref (proc);
200 }
201 #endif
202
203 static void
204 test_exit1 (void)
205 {
206   GError *local_error = NULL;
207   GError **error = &local_error;
208   GPtrArray *args;
209   GSubprocess *proc;
210
211   args = get_test_subprocess_args ("exit1", NULL);
212   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
213   g_ptr_array_free (args, TRUE);
214   g_assert_no_error (local_error);
215
216   g_subprocess_wait_check (proc, NULL, error);
217   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
218   g_clear_error (error);
219
220   g_object_unref (proc);
221 }
222
223 typedef struct {
224   GMainLoop    *loop;
225   GCancellable *cancellable;
226   gboolean      cb_called;
227 } TestExit1CancelData;
228
229 static gboolean
230 test_exit1_cancel_idle_quit_cb (gpointer user_data)
231 {
232   GMainLoop *loop = user_data;
233   g_main_loop_quit (loop);
234   return G_SOURCE_REMOVE;
235 }
236
237 static void
238 test_exit1_cancel_wait_check_cb (GObject      *source,
239                                  GAsyncResult *result,
240                                  gpointer      user_data)
241 {
242   GSubprocess *subprocess = G_SUBPROCESS (source);
243   TestExit1CancelData *data = user_data;
244   gboolean ret;
245   GError *error = NULL;
246
247   g_assert_false (data->cb_called);
248   data->cb_called = TRUE;
249
250   ret = g_subprocess_wait_check_finish (subprocess, result, &error);
251   g_assert_false (ret);
252   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
253   g_clear_error (&error);
254
255   g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
256 }
257
258 static void
259 test_exit1_cancel (void)
260 {
261   GError *local_error = NULL;
262   GError **error = &local_error;
263   GPtrArray *args;
264   GSubprocess *proc;
265   TestExit1CancelData data = { 0 };
266
267   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=786456");
268
269   args = get_test_subprocess_args ("exit1", NULL);
270   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
271   g_ptr_array_free (args, TRUE);
272   g_assert_no_error (local_error);
273
274   data.loop = g_main_loop_new (NULL, FALSE);
275   data.cancellable = g_cancellable_new ();
276   g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_wait_check_cb, &data);
277
278   g_subprocess_wait_check (proc, NULL, error);
279   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
280   g_clear_error (error);
281
282   g_cancellable_cancel (data.cancellable);
283   g_main_loop_run (data.loop);
284
285   g_object_unref (proc);
286   g_main_loop_unref (data.loop);
287   g_clear_object (&data.cancellable);
288 }
289
290 static void
291 test_exit1_cancel_in_cb_wait_check_cb (GObject      *source,
292                                        GAsyncResult *result,
293                                        gpointer      user_data)
294 {
295   GSubprocess *subprocess = G_SUBPROCESS (source);
296   TestExit1CancelData *data = user_data;
297   gboolean ret;
298   GError *error = NULL;
299
300   g_assert_false (data->cb_called);
301   data->cb_called = TRUE;
302
303   ret = g_subprocess_wait_check_finish (subprocess, result, &error);
304   g_assert_false (ret);
305   g_assert_error (error, G_SPAWN_EXIT_ERROR, 1);
306   g_clear_error (&error);
307
308   g_cancellable_cancel (data->cancellable);
309
310   g_idle_add (test_exit1_cancel_idle_quit_cb, data->loop);
311 }
312
313 static void
314 test_exit1_cancel_in_cb (void)
315 {
316   GError *local_error = NULL;
317   GError **error = &local_error;
318   GPtrArray *args;
319   GSubprocess *proc;
320   TestExit1CancelData data = { 0 };
321
322   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=786456");
323
324   args = get_test_subprocess_args ("exit1", NULL);
325   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
326   g_ptr_array_free (args, TRUE);
327   g_assert_no_error (local_error);
328
329   data.loop = g_main_loop_new (NULL, FALSE);
330   data.cancellable = g_cancellable_new ();
331   g_subprocess_wait_check_async (proc, data.cancellable, test_exit1_cancel_in_cb_wait_check_cb, &data);
332
333   g_subprocess_wait_check (proc, NULL, error);
334   g_assert_error (local_error, G_SPAWN_EXIT_ERROR, 1);
335   g_clear_error (error);
336
337   g_main_loop_run (data.loop);
338
339   g_object_unref (proc);
340   g_main_loop_unref (data.loop);
341   g_clear_object (&data.cancellable);
342 }
343
344 static gchar *
345 splice_to_string (GInputStream   *stream,
346                   GError        **error)
347 {
348   GMemoryOutputStream *buffer = NULL;
349   char *ret = NULL;
350
351   buffer = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
352   if (g_output_stream_splice ((GOutputStream*)buffer, stream, 0, NULL, error) < 0)
353     goto out;
354
355   if (!g_output_stream_write ((GOutputStream*)buffer, "\0", 1, NULL, error))
356     goto out;
357
358   if (!g_output_stream_close ((GOutputStream*)buffer, NULL, error))
359     goto out;
360
361   ret = g_memory_output_stream_steal_data (buffer);
362  out:
363   g_clear_object (&buffer);
364   return ret;
365 }
366
367 static void
368 test_echo1 (void)
369 {
370   GError *local_error = NULL;
371   GError **error = &local_error;
372   GSubprocess *proc;
373   GPtrArray *args;
374   GInputStream *stdout_stream;
375   gchar *result;
376
377   args = get_test_subprocess_args ("echo", "hello", "world!", NULL);
378   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_STDOUT_PIPE, error);
379   g_ptr_array_free (args, TRUE);
380   g_assert_no_error (local_error);
381
382   stdout_stream = g_subprocess_get_stdout_pipe (proc);
383
384   result = splice_to_string (stdout_stream, error);
385   g_assert_no_error (local_error);
386
387   g_assert_cmpstr (result, ==, "hello" LINEEND "world!" LINEEND);
388
389   g_free (result);
390   g_object_unref (proc);
391 }
392
393 #ifdef G_OS_UNIX
394 static void
395 test_echo_merged (void)
396 {
397   GError *local_error = NULL;
398   GError **error = &local_error;
399   GSubprocess *proc;
400   GPtrArray *args;
401   GInputStream *stdout_stream;
402   gchar *result;
403
404   args = get_test_subprocess_args ("echo-stdout-and-stderr", "merge", "this", NULL);
405   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
406                             G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE,
407                             error);
408   g_ptr_array_free (args, TRUE);
409   g_assert_no_error (local_error);
410
411   stdout_stream = g_subprocess_get_stdout_pipe (proc);
412   result = splice_to_string (stdout_stream, error);
413   g_assert_no_error (local_error);
414
415   g_assert_cmpstr (result, ==, "merge\nmerge\nthis\nthis\n");
416
417   g_free (result);
418   g_object_unref (proc);
419 }
420 #endif
421
422 typedef struct {
423   guint events_pending;
424   GMainLoop *loop;
425 } TestCatData;
426
427 static void
428 test_cat_on_input_splice_complete (GObject      *object,
429                                    GAsyncResult *result,
430                                    gpointer      user_data)
431 {
432   TestCatData *data = user_data;
433   GError *error = NULL;
434
435   (void)g_output_stream_splice_finish ((GOutputStream*)object, result, &error);
436   g_assert_no_error (error);
437
438   data->events_pending--;
439   if (data->events_pending == 0)
440     g_main_loop_quit (data->loop);
441 }
442
443 static void
444 test_cat_utf8 (void)
445 {
446   GError *local_error = NULL;
447   GError **error = &local_error;
448   GSubprocess *proc;
449   GPtrArray *args;
450   GBytes *input_buf;
451   GBytes *output_buf;
452   GInputStream *input_buf_stream = NULL;
453   GOutputStream *output_buf_stream = NULL;
454   GOutputStream *stdin_stream = NULL;
455   GInputStream *stdout_stream = NULL;
456   TestCatData data;
457
458   memset (&data, 0, sizeof (data));
459   data.loop = g_main_loop_new (NULL, TRUE);
460
461   args = get_test_subprocess_args ("cat", NULL);
462   proc = g_subprocess_newv ((const gchar * const *) args->pdata,
463                             G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
464                             error);
465   g_ptr_array_free (args, TRUE);
466   g_assert_no_error (local_error);
467
468   stdin_stream = g_subprocess_get_stdin_pipe (proc);
469   stdout_stream = g_subprocess_get_stdout_pipe (proc);
470
471   input_buf = g_bytes_new_static ("hello, world!", strlen ("hello, world!"));
472   input_buf_stream = g_memory_input_stream_new_from_bytes (input_buf);
473   g_bytes_unref (input_buf);
474
475   output_buf_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
476
477   g_output_stream_splice_async (stdin_stream, input_buf_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
478                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
479                                 &data);
480   data.events_pending++;
481   g_output_stream_splice_async (output_buf_stream, stdout_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
482                                 G_PRIORITY_DEFAULT, NULL, test_cat_on_input_splice_complete,
483                                 &data);
484   data.events_pending++;
485
486   g_main_loop_run (data.loop);
487
488   g_subprocess_wait_check (proc, NULL, error);
489   g_assert_no_error (local_error);
490
491   output_buf = g_memory_output_stream_steal_as_bytes ((GMemoryOutputStream*)output_buf_stream);
492
493   g_assert_cmpmem (g_bytes_get_data (output_buf, NULL),
494                    g_bytes_get_size (output_buf),
495                    "hello, world!", 13);
496
497   g_bytes_unref (output_buf);
498   g_main_loop_unref (data.loop);
499   g_object_unref (input_buf_stream);
500   g_object_unref (output_buf_stream);
501   g_object_unref (proc);
502 }
503
504 static gpointer
505 cancel_soon (gpointer user_data)
506 {
507   GCancellable *cancellable = user_data;
508
509   g_usleep (G_TIME_SPAN_SECOND);
510   g_cancellable_cancel (cancellable);
511   g_object_unref (cancellable);
512
513   return NULL;
514 }
515
516 static void
517 test_cat_eof (void)
518 {
519   GCancellable *cancellable;
520   GError *error = NULL;
521   GSubprocess *cat;
522   gboolean result;
523   gchar buffer;
524   gssize s;
525
526 #ifdef G_OS_WIN32
527   g_test_skip ("This test has not been ported to Win32");
528   return;
529 #endif
530
531   /* Spawn 'cat' */
532   cat = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "cat", NULL);
533   g_assert_no_error (error);
534   g_assert_nonnull (cat);
535
536   /* Make sure that reading stdout blocks (until we cancel) */
537   cancellable = g_cancellable_new ();
538   g_thread_unref (g_thread_new ("cancel thread", cancel_soon, g_object_ref (cancellable)));
539   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, cancellable, &error);
540   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
541   g_assert_cmpint (s, ==, -1);
542   g_object_unref (cancellable);
543   g_clear_error (&error);
544
545   /* Close the stream (EOF on cat's stdin) */
546   result = g_output_stream_close (g_subprocess_get_stdin_pipe (cat), NULL, &error);
547   g_assert_no_error (error);
548   g_assert_true (result);
549
550   /* Now check that reading cat's stdout gets us an EOF (since it quit) */
551   s = g_input_stream_read (g_subprocess_get_stdout_pipe (cat), &buffer, sizeof buffer, NULL, &error);
552   g_assert_no_error (error);
553   g_assert_false (s);
554
555   /* Check that the process has exited as a result of the EOF */
556   result = g_subprocess_wait (cat, NULL, &error);
557   g_assert_no_error (error);
558   g_assert_true (g_subprocess_get_if_exited (cat));
559   g_assert_cmpint (g_subprocess_get_exit_status (cat), ==, 0);
560   g_assert_true (result);
561
562   g_object_unref (cat);
563 }
564
565 typedef struct {
566   guint events_pending;
567   gboolean caught_error;
568   GError *error;
569   GMainLoop *loop;
570
571   gint counter;
572   GOutputStream *first_stdin;
573 } TestMultiSpliceData;
574
575 static void
576 on_one_multi_splice_done (GObject       *obj,
577                           GAsyncResult  *res,
578                           gpointer       user_data)
579 {
580   TestMultiSpliceData *data = user_data;
581
582   if (!data->caught_error)
583     {
584       if (g_output_stream_splice_finish ((GOutputStream*)obj, res, &data->error) < 0)
585         data->caught_error = TRUE;
586     }
587
588   data->events_pending--;
589   if (data->events_pending == 0)
590     g_main_loop_quit (data->loop);
591 }
592
593 static gboolean
594 on_idle_multisplice (gpointer     user_data)
595 {
596   TestMultiSpliceData *data = user_data;
597
598   if (data->counter >= TOTAL_HELLOS || data->caught_error)
599     {
600       if (!g_output_stream_close (data->first_stdin, NULL, &data->error))
601         data->caught_error = TRUE;
602       data->events_pending--;
603       if (data->events_pending == 0)
604         {
605           g_main_loop_quit (data->loop);
606         }
607       return FALSE;
608     }
609   else
610     {
611       int i;
612       for (i = 0; i < data->counter; i++)
613         {
614           gsize bytes_written;
615           if (!g_output_stream_write_all (data->first_stdin, HELLO_WORLD,
616                                           strlen (HELLO_WORLD), &bytes_written,
617                                           NULL, &data->error))
618             {
619               data->caught_error = TRUE;
620               return FALSE;
621             }
622         }
623       data->counter *= 2;
624       return TRUE;
625     }
626 }
627
628 static void
629 on_subprocess_exited (GObject         *object,
630                       GAsyncResult    *result,
631                       gpointer         user_data)
632 {
633   GSubprocess *subprocess = G_SUBPROCESS (object);
634   TestMultiSpliceData *data = user_data;
635   GError *error = NULL;
636
637   if (!g_subprocess_wait_finish (subprocess, result, &error))
638     {
639       if (!data->caught_error)
640         {
641           data->caught_error = TRUE;
642           g_propagate_error (&data->error, error);
643         }
644     }
645   g_spawn_check_wait_status (g_subprocess_get_status (subprocess), &error);
646   g_assert_no_error (error);
647   data->events_pending--;
648   if (data->events_pending == 0)
649     g_main_loop_quit (data->loop);
650 }
651
652 static void
653 test_multi_1 (void)
654 {
655   GError *local_error = NULL;
656   GError **error = &local_error;
657   GPtrArray *args;
658   GSubprocessLauncher *launcher;
659   GSubprocess *first;
660   GSubprocess *second;
661   GSubprocess *third;
662   GOutputStream *first_stdin;
663   GInputStream *first_stdout;
664   GOutputStream *second_stdin;
665   GInputStream *second_stdout;
666   GOutputStream *third_stdin;
667   GInputStream *third_stdout;
668   GOutputStream *membuf;
669   TestMultiSpliceData data;
670   int splice_flags = G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
671
672   args = get_test_subprocess_args ("cat", NULL);
673   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);
674   first = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
675   g_assert_no_error (local_error);
676   second = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
677   g_assert_no_error (local_error);
678   third = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
679   g_assert_no_error (local_error);
680
681   g_ptr_array_free (args, TRUE);
682
683   membuf = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
684
685   first_stdin = g_subprocess_get_stdin_pipe (first);
686   first_stdout = g_subprocess_get_stdout_pipe (first);
687   second_stdin = g_subprocess_get_stdin_pipe (second);
688   second_stdout = g_subprocess_get_stdout_pipe (second);
689   third_stdin = g_subprocess_get_stdin_pipe (third);
690   third_stdout = g_subprocess_get_stdout_pipe (third);
691
692   memset (&data, 0, sizeof (data));
693   data.loop = g_main_loop_new (NULL, TRUE);
694   data.counter = 1;
695   data.first_stdin = first_stdin;
696
697   data.events_pending++;
698   g_output_stream_splice_async (second_stdin, first_stdout, splice_flags, G_PRIORITY_DEFAULT,
699                                 NULL, on_one_multi_splice_done, &data);
700   data.events_pending++;
701   g_output_stream_splice_async (third_stdin, second_stdout, splice_flags, G_PRIORITY_DEFAULT,
702                                 NULL, on_one_multi_splice_done, &data);
703   data.events_pending++;
704   g_output_stream_splice_async (membuf, third_stdout, splice_flags, G_PRIORITY_DEFAULT,
705                                 NULL, on_one_multi_splice_done, &data);
706
707   data.events_pending++;
708   g_timeout_add (250, on_idle_multisplice, &data);
709
710   data.events_pending++;
711   g_subprocess_wait_async (first, NULL, on_subprocess_exited, &data);
712   data.events_pending++;
713   g_subprocess_wait_async (second, NULL, on_subprocess_exited, &data);
714   data.events_pending++;
715   g_subprocess_wait_async (third, NULL, on_subprocess_exited, &data);
716
717   g_main_loop_run (data.loop);
718
719   g_assert_false (data.caught_error);
720   g_assert_no_error (data.error);
721
722   g_assert_cmpint (g_memory_output_stream_get_data_size ((GMemoryOutputStream*)membuf), ==, SPLICELEN);
723
724   g_main_loop_unref (data.loop);
725   g_object_unref (membuf);
726   g_object_unref (launcher);
727   g_object_unref (first);
728   g_object_unref (second);
729   g_object_unref (third);
730 }
731
732 typedef struct {
733   GSubprocessFlags flags;
734   gboolean is_utf8;
735   gboolean running;
736   GError *error;
737 } TestAsyncCommunicateData;
738
739 static void
740 on_communicate_complete (GObject               *proc,
741                          GAsyncResult          *result,
742                          gpointer               user_data)
743 {
744   TestAsyncCommunicateData *data = user_data;
745   GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
746   char *stdout_str = NULL, *stderr_str = NULL;
747   const guint8 *stdout_data;
748   gsize stdout_len;
749
750   data->running = FALSE;
751   if (data->is_utf8)
752     (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
753                                                  &stdout_str, &stderr_str, &data->error);
754   else
755     (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
756                                             &stdout_bytes, &stderr_bytes, &data->error);
757   if (data->error)
758       return;
759
760   if (data->flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
761     {
762       if (data->is_utf8)
763         {
764           g_assert_nonnull (stdout_str);
765           stdout_data = (guint8*)stdout_str;
766           stdout_len = strlen (stdout_str);
767         }
768       else
769         {
770           g_assert_nonnull (stdout_bytes);
771           stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
772         }
773
774       g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
775     }
776   else
777     {
778       g_assert_null (stdout_str);
779       g_assert_null (stdout_bytes);
780     }
781
782   if (data->flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
783     {
784       if (data->is_utf8)
785         g_assert_nonnull (stderr_str);
786       else
787         g_assert_nonnull (stderr_bytes);
788     }
789   else
790     {
791       g_assert_null (stderr_str);
792       g_assert_null (stderr_bytes);
793     }
794
795   g_clear_pointer (&stdout_bytes, g_bytes_unref);
796   g_clear_pointer (&stderr_bytes, g_bytes_unref);
797   g_free (stdout_str);
798   g_free (stderr_str);
799 }
800
801 /* Test g_subprocess_communicate_async() works correctly with a variety of flags,
802  * as passed in via @test_data. */
803 static void
804 test_communicate_async (gconstpointer test_data)
805 {
806   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
807   GError *error = NULL;
808   GPtrArray *args;
809   TestAsyncCommunicateData data = { flags, 0, 0, NULL };
810   GSubprocess *proc;
811   GCancellable *cancellable = NULL;
812   GBytes *input;
813   const char *hellostring;
814
815   args = get_test_subprocess_args ("cat", NULL);
816   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
817                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
818                             &error);
819   g_assert_no_error (error);
820   g_ptr_array_free (args, TRUE);
821
822   /* Include a leading hash and trailing newline so that if this gets onto the
823    * test’s stdout, it doesn’t mess up TAP output. */
824   hellostring = "# hello world\n";
825   input = g_bytes_new_static (hellostring, strlen (hellostring));
826
827   g_subprocess_communicate_async (proc, input,
828                                   cancellable,
829                                   on_communicate_complete, 
830                                   &data);
831   
832   data.running = TRUE;
833   while (data.running)
834     g_main_context_iteration (NULL, TRUE);
835
836   g_assert_no_error (data.error);
837
838   g_bytes_unref (input);
839   g_object_unref (proc);
840 }
841
842 /* Test g_subprocess_communicate() works correctly with a variety of flags,
843  * as passed in via @test_data. */
844 static void
845 test_communicate (gconstpointer test_data)
846 {
847   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
848   GError *error = NULL;
849   GPtrArray *args;
850   GSubprocess *proc;
851   GCancellable *cancellable = NULL;
852   GBytes *input;
853   const gchar *hellostring;
854   GBytes *stdout_bytes, *stderr_bytes;
855   const gchar *stdout_data;
856   gsize stdout_len;
857
858   args = get_test_subprocess_args ("cat", NULL);
859   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
860                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
861                             &error);
862   g_assert_no_error (error);
863   g_ptr_array_free (args, TRUE);
864
865   /* Include a leading hash and trailing newline so that if this gets onto the
866    * test’s stdout, it doesn’t mess up TAP output. */
867   hellostring = "# hello world\n";
868   input = g_bytes_new_static (hellostring, strlen (hellostring));
869
870   g_subprocess_communicate (proc, input, cancellable, &stdout_bytes, &stderr_bytes, &error);
871   g_assert_no_error (error);
872
873   if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
874     {
875       stdout_data = g_bytes_get_data (stdout_bytes, &stdout_len);
876       g_assert_cmpmem (stdout_data, stdout_len, "# hello world" LINEEND, 13 + strlen (LINEEND));
877     }
878   else
879     g_assert_null (stdout_bytes);
880   if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
881     g_assert_nonnull (stderr_bytes);
882   else
883     g_assert_null (stderr_bytes);
884
885   g_bytes_unref (input);
886   g_clear_pointer (&stdout_bytes, g_bytes_unref);
887   g_clear_pointer (&stderr_bytes, g_bytes_unref);
888   g_object_unref (proc);
889 }
890
891 typedef struct {
892   GSubprocess  *proc;
893   GCancellable *cancellable;
894   gboolean is_utf8;
895   gboolean running;
896   GError *error;
897 } TestCancelledCommunicateData;
898
899 static gboolean
900 on_test_communicate_cancelled_idle (gpointer user_data)
901 {
902   TestCancelledCommunicateData *data = user_data;
903   GBytes *input;
904   const gchar *hellostring;
905   GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
906   gchar *stdout_buf = NULL, *stderr_buf = NULL;
907
908   /* Include a leading hash and trailing newline so that if this gets onto the
909    * test’s stdout, it doesn’t mess up TAP output. */
910   hellostring = "# hello world\n";
911   input = g_bytes_new_static (hellostring, strlen (hellostring));
912
913   if (data->is_utf8)
914     g_subprocess_communicate_utf8 (data->proc, hellostring, data->cancellable,
915                                    &stdout_buf, &stderr_buf, &data->error);
916   else
917     g_subprocess_communicate (data->proc, input, data->cancellable, &stdout_bytes,
918                               &stderr_bytes, &data->error);
919
920   data->running = FALSE;
921
922   if (data->is_utf8)
923     {
924       g_assert_null (stdout_buf);
925       g_assert_null (stderr_buf);
926     }
927   else
928     {
929       g_assert_null (stdout_bytes);
930       g_assert_null (stderr_bytes);
931     }
932
933   g_bytes_unref (input);
934
935   return G_SOURCE_REMOVE;
936 }
937
938 /* Test g_subprocess_communicate() can be cancelled correctly */
939 static void
940 test_communicate_cancelled (gconstpointer test_data)
941 {
942   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
943   GPtrArray *args;
944   GSubprocess *proc;
945   GCancellable *cancellable = NULL;
946   GError *error = NULL;
947   TestCancelledCommunicateData data = { 0 };
948
949   args = get_test_subprocess_args ("cat", NULL);
950   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
951                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
952                             &error);
953   g_assert_no_error (error);
954   g_ptr_array_free (args, TRUE);
955
956   cancellable = g_cancellable_new ();
957
958   data.proc = proc;
959   data.cancellable = cancellable;
960   data.error = error;
961
962   g_cancellable_cancel (cancellable);
963   g_idle_add (on_test_communicate_cancelled_idle, &data);
964
965   data.running = TRUE;
966   while (data.running)
967     g_main_context_iteration (NULL, TRUE);
968
969   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
970   g_clear_error (&data.error);
971
972   g_object_unref (cancellable);
973   g_object_unref (proc);
974 }
975
976 static void
977 on_communicate_cancelled_complete (GObject               *proc,
978                                    GAsyncResult          *result,
979                                    gpointer               user_data)
980 {
981   TestAsyncCommunicateData *data = user_data;
982   GBytes *stdout_bytes = NULL, *stderr_bytes = NULL;
983   char *stdout_str = NULL, *stderr_str = NULL;
984
985   data->running = FALSE;
986   if (data->is_utf8)
987     (void) g_subprocess_communicate_utf8_finish ((GSubprocess*)proc, result,
988                                                  &stdout_str, &stderr_str, &data->error);
989   else
990     (void) g_subprocess_communicate_finish ((GSubprocess*)proc, result,
991                                             &stdout_bytes, &stderr_bytes, &data->error);
992
993   if (data->is_utf8)
994     {
995       g_assert_null (stdout_str);
996       g_assert_null (stderr_str);
997     }
998   else
999     {
1000       g_assert_null (stdout_bytes);
1001       g_assert_null (stderr_bytes);
1002     }
1003 }
1004
1005 /* Test g_subprocess_communicate_async() can be cancelled correctly,
1006  * as passed in via @test_data. */
1007 static void
1008 test_communicate_cancelled_async (gconstpointer test_data)
1009 {
1010   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1011   GError *error = NULL;
1012   GPtrArray *args;
1013   TestAsyncCommunicateData data = { 0 };
1014   GSubprocess *proc;
1015   GCancellable *cancellable = NULL;
1016   GBytes *input;
1017   const char *hellostring;
1018
1019   args = get_test_subprocess_args ("cat", NULL);
1020   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1021                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1022                             &error);
1023   g_assert_no_error (error);
1024   g_ptr_array_free (args, TRUE);
1025
1026   /* Include a leading hash and trailing newline so that if this gets onto the
1027    * test’s stdout, it doesn’t mess up TAP output. */
1028   hellostring = "# hello world\n";
1029   input = g_bytes_new_static (hellostring, strlen (hellostring));
1030
1031   cancellable = g_cancellable_new ();
1032
1033   g_subprocess_communicate_async (proc, input,
1034                                   cancellable,
1035                                   on_communicate_cancelled_complete,
1036                                   &data);
1037
1038   g_cancellable_cancel (cancellable);
1039
1040   data.running = TRUE;
1041   while (data.running)
1042     g_main_context_iteration (NULL, TRUE);
1043
1044   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1045   g_clear_error (&data.error);
1046
1047   g_bytes_unref (input);
1048   g_object_unref (cancellable);
1049   g_object_unref (proc);
1050 }
1051
1052 /* Test g_subprocess_communicate_utf8_async() works correctly with a variety of
1053  * flags, as passed in via @test_data. */
1054 static void
1055 test_communicate_utf8_async (gconstpointer test_data)
1056 {
1057   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1058   GError *error = NULL;
1059   GPtrArray *args;
1060   TestAsyncCommunicateData data = { flags, 0, 0, NULL };
1061   GSubprocess *proc;
1062   GCancellable *cancellable = NULL;
1063
1064   args = get_test_subprocess_args ("cat", NULL);
1065   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1066                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1067                             &error);
1068   g_assert_no_error (error);
1069   g_ptr_array_free (args, TRUE);
1070
1071   data.is_utf8 = TRUE;
1072   g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1073                                        cancellable,
1074                                        on_communicate_complete, 
1075                                        &data);
1076   
1077   data.running = TRUE;
1078   while (data.running)
1079     g_main_context_iteration (NULL, TRUE);
1080
1081   g_assert_no_error (data.error);
1082
1083   g_object_unref (proc);
1084 }
1085
1086 /* Test g_subprocess_communicate_utf8_async() can be cancelled correctly. */
1087 static void
1088 test_communicate_utf8_cancelled_async (gconstpointer test_data)
1089 {
1090   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1091   GError *error = NULL;
1092   GPtrArray *args;
1093   TestAsyncCommunicateData data = { flags, 0, 0, NULL };
1094   GSubprocess *proc;
1095   GCancellable *cancellable = NULL;
1096
1097   args = get_test_subprocess_args ("cat", NULL);
1098   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1099                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1100                             &error);
1101   g_assert_no_error (error);
1102   g_ptr_array_free (args, TRUE);
1103
1104   cancellable = g_cancellable_new ();
1105   data.is_utf8 = TRUE;
1106   g_subprocess_communicate_utf8_async (proc, "# hello world\n",
1107                                        cancellable,
1108                                        on_communicate_cancelled_complete,
1109                                        &data);
1110
1111   g_cancellable_cancel (cancellable);
1112
1113   data.running = TRUE;
1114   while (data.running)
1115     g_main_context_iteration (NULL, TRUE);
1116
1117   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1118   g_clear_error (&data.error);
1119
1120   g_object_unref (cancellable);
1121   g_object_unref (proc);
1122 }
1123
1124 /* Test g_subprocess_communicate_utf8() works correctly with a variety of flags,
1125  * as passed in via @test_data. */
1126 static void
1127 test_communicate_utf8 (gconstpointer test_data)
1128 {
1129   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1130   GError *error = NULL;
1131   GPtrArray *args;
1132   GSubprocess *proc;
1133   GCancellable *cancellable = NULL;
1134   const gchar *stdin_buf;
1135   gchar *stdout_buf, *stderr_buf;
1136
1137   args = get_test_subprocess_args ("cat", NULL);
1138   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1139                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1140                             &error);
1141   g_assert_no_error (error);
1142   g_ptr_array_free (args, TRUE);
1143
1144   /* Include a leading hash and trailing newline so that if this gets onto the
1145    * test’s stdout, it doesn’t mess up TAP output. */
1146   stdin_buf = "# hello world\n";
1147
1148   g_subprocess_communicate_utf8 (proc, stdin_buf, cancellable, &stdout_buf, &stderr_buf, &error);
1149   g_assert_no_error (error);
1150
1151   if (flags & G_SUBPROCESS_FLAGS_STDOUT_PIPE)
1152     g_assert_cmpstr (stdout_buf, ==, "# hello world" LINEEND);
1153   else
1154     g_assert_null (stdout_buf);
1155   if (flags & G_SUBPROCESS_FLAGS_STDERR_PIPE)
1156     g_assert_nonnull (stderr_buf);
1157   else     g_assert_null (stderr_buf);
1158
1159   g_free (stdout_buf);
1160   g_free (stderr_buf);
1161   g_object_unref (proc);
1162 }
1163
1164 /* Test g_subprocess_communicate_utf8() can be cancelled correctly */
1165 static void
1166 test_communicate_utf8_cancelled (gconstpointer test_data)
1167 {
1168   GSubprocessFlags flags = GPOINTER_TO_INT (test_data);
1169   GPtrArray *args;
1170   GSubprocess *proc;
1171   GCancellable *cancellable = NULL;
1172   GError *error = NULL;
1173   TestCancelledCommunicateData data = { 0 };
1174
1175   args = get_test_subprocess_args ("cat", NULL);
1176   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1177                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1178                             &error);
1179   g_assert_no_error (error);
1180   g_ptr_array_free (args, TRUE);
1181
1182   cancellable = g_cancellable_new ();
1183
1184   data.proc = proc;
1185   data.cancellable = cancellable;
1186   data.error = error;
1187
1188   g_cancellable_cancel (cancellable);
1189   g_idle_add (on_test_communicate_cancelled_idle, &data);
1190
1191   data.is_utf8 = TRUE;
1192   data.running = TRUE;
1193   while (data.running)
1194     g_main_context_iteration (NULL, TRUE);
1195
1196   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1197   g_clear_error (&data.error);
1198
1199   g_object_unref (cancellable);
1200   g_object_unref (proc);
1201 }
1202
1203 static void
1204 test_communicate_nothing (void)
1205 {
1206   GError *error = NULL;
1207   GPtrArray *args;
1208   GSubprocess *proc;
1209   GCancellable *cancellable = NULL;
1210   gchar *stdout_buf;
1211
1212   args = get_test_subprocess_args ("cat", NULL);
1213   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1214                             G_SUBPROCESS_FLAGS_STDIN_PIPE
1215                             | G_SUBPROCESS_FLAGS_STDOUT_PIPE
1216                             | G_SUBPROCESS_FLAGS_STDERR_MERGE,
1217                             &error);
1218   g_assert_no_error (error);
1219   g_ptr_array_free (args, TRUE);
1220
1221   g_subprocess_communicate_utf8 (proc, "", cancellable, &stdout_buf, NULL, &error);
1222   g_assert_no_error (error);
1223
1224   g_assert_cmpstr (stdout_buf, ==, "");
1225
1226   g_free (stdout_buf);
1227
1228   g_object_unref (proc);
1229 }
1230
1231 static void
1232 test_communicate_utf8_async_invalid (void)
1233 {
1234   GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1235   GError *error = NULL;
1236   GPtrArray *args;
1237   TestAsyncCommunicateData data = { flags, 0, 0, NULL };
1238   GSubprocess *proc;
1239   GCancellable *cancellable = NULL;
1240
1241   args = get_test_subprocess_args ("cat", NULL);
1242   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1243                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1244                             &error);
1245   g_assert_no_error (error);
1246   g_ptr_array_free (args, TRUE);
1247
1248   data.is_utf8 = TRUE;
1249   g_subprocess_communicate_utf8_async (proc, "\xFF\xFF",
1250                                        cancellable,
1251                                        on_communicate_complete, 
1252                                        &data);
1253   
1254   data.running = TRUE;
1255   while (data.running)
1256     g_main_context_iteration (NULL, TRUE);
1257
1258   g_assert_error (data.error, G_IO_ERROR, G_IO_ERROR_FAILED);
1259   g_error_free (data.error);
1260
1261   g_object_unref (proc);
1262 }
1263
1264 /* Test that invalid UTF-8 received using g_subprocess_communicate_utf8()
1265  * results in an error. */
1266 static void
1267 test_communicate_utf8_invalid (void)
1268 {
1269   GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE;
1270   GError *local_error = NULL;
1271   gboolean ret;
1272   GPtrArray *args;
1273   gchar *stdout_str = NULL, *stderr_str = NULL;
1274   GSubprocess *proc;
1275
1276   args = get_test_subprocess_args ("cat", NULL);
1277   proc = g_subprocess_newv ((const gchar* const*)args->pdata,
1278                             G_SUBPROCESS_FLAGS_STDIN_PIPE | flags,
1279                             &local_error);
1280   g_assert_no_error (local_error);
1281   g_ptr_array_free (args, TRUE);
1282
1283   ret = g_subprocess_communicate_utf8 (proc, "\xFF\xFF", NULL,
1284                                        &stdout_str, &stderr_str, &local_error);
1285   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_FAILED);
1286   g_error_free (local_error);
1287   g_assert_false (ret);
1288
1289   g_assert_null (stdout_str);
1290   g_assert_null (stderr_str);
1291
1292   g_object_unref (proc);
1293 }
1294
1295 static void
1296 send_terminate (gpointer   user_data)
1297 {
1298   GSubprocess *proc = user_data;
1299
1300   g_subprocess_force_exit (proc);
1301 }
1302
1303 static void
1304 on_request_quit_exited (GObject        *object,
1305                         GAsyncResult   *result,
1306                         gpointer        user_data)
1307 {
1308   GSubprocess *subprocess = G_SUBPROCESS (object);
1309   GError *error = NULL;
1310
1311   g_subprocess_wait_finish (subprocess, result, &error);
1312   g_assert_no_error (error);
1313 #ifdef G_OS_UNIX
1314   g_assert_true (g_subprocess_get_if_signaled (subprocess));
1315   g_assert_cmpint (g_subprocess_get_term_sig (subprocess), ==, 9);
1316 #endif
1317   g_spawn_check_wait_status (g_subprocess_get_status (subprocess), &error);
1318   g_assert_nonnull (error);
1319   g_clear_error (&error);
1320
1321   g_main_loop_quit ((GMainLoop*)user_data);
1322 }
1323
1324 static void
1325 test_terminate (void)
1326 {
1327   GError *local_error = NULL;
1328   GError **error = &local_error;
1329   GSubprocess *proc;
1330   GPtrArray *args;
1331   GMainLoop *loop;
1332   const gchar *id;
1333
1334   args = get_test_subprocess_args ("sleep-forever", NULL);
1335   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1336   g_ptr_array_free (args, TRUE);
1337   g_assert_no_error (local_error);
1338
1339   id = g_subprocess_get_identifier (proc);
1340   g_assert_nonnull (id);
1341
1342   loop = g_main_loop_new (NULL, TRUE);
1343
1344   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1345
1346   g_timeout_add_seconds_once (3, send_terminate, proc);
1347
1348   g_main_loop_run (loop);
1349
1350   g_main_loop_unref (loop);
1351   g_object_unref (proc);
1352 }
1353
1354 #ifdef G_OS_UNIX
1355 static void
1356 send_signal (gpointer user_data)
1357 {
1358   GSubprocess *proc = user_data;
1359
1360   g_subprocess_send_signal (proc, SIGKILL);
1361 }
1362
1363 static void
1364 test_signal (void)
1365 {
1366   GError *local_error = NULL;
1367   GError **error = &local_error;
1368   GSubprocess *proc;
1369   GPtrArray *args;
1370   GMainLoop *loop;
1371
1372   args = get_test_subprocess_args ("sleep-forever", NULL);
1373   proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error);
1374   g_ptr_array_free (args, TRUE);
1375   g_assert_no_error (local_error);
1376
1377   loop = g_main_loop_new (NULL, TRUE);
1378
1379   g_subprocess_wait_async (proc, NULL, on_request_quit_exited, loop);
1380
1381   g_timeout_add_seconds_once (3, send_signal, proc);
1382
1383   g_main_loop_run (loop);
1384
1385   g_main_loop_unref (loop);
1386   g_object_unref (proc);
1387 }
1388 #endif
1389
1390 static void
1391 test_env (void)
1392 {
1393   GError *local_error = NULL;
1394   GError **error = &local_error;
1395   GSubprocessLauncher *launcher;
1396   GSubprocess *proc;
1397   GPtrArray *args;
1398   GInputStream *stdout_stream;
1399   gchar *result;
1400   gchar *envp[] = { NULL, "ONE=1", "TWO=1", "THREE=3", "FOUR=1", NULL };
1401   gchar **split;
1402
1403   envp[0] = g_strdup_printf ("PATH=%s", g_getenv ("PATH"));
1404   args = get_test_subprocess_args ("env", NULL);
1405   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1406   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1407   g_subprocess_launcher_set_environ (launcher, envp);
1408   g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1409   g_subprocess_launcher_setenv (launcher, "THREE", "1", FALSE);
1410   g_subprocess_launcher_unsetenv (launcher, "FOUR");
1411
1412   g_assert_null (g_subprocess_launcher_getenv (launcher, "FOUR"));
1413    
1414   proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1415   g_ptr_array_free (args, TRUE);
1416   g_assert_no_error (local_error);
1417   g_free (envp[0]);
1418
1419   stdout_stream = g_subprocess_get_stdout_pipe (proc);
1420
1421   result = splice_to_string (stdout_stream, error);
1422   split = g_strsplit (result, LINEEND, -1);
1423   g_assert_cmpstr (g_environ_getenv (split, "ONE"), ==, "1");
1424   g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1425   g_assert_cmpstr (g_environ_getenv (split, "THREE"), ==, "3");
1426   g_assert_null (g_environ_getenv (split, "FOUR"));
1427
1428   g_strfreev (split);
1429   g_free (result);
1430   g_object_unref (proc);
1431   g_object_unref (launcher);
1432 }
1433
1434 /* Test that explicitly inheriting and modifying the parent process’
1435  * environment works. */
1436 static void
1437 test_env_inherit (void)
1438 {
1439   GError *local_error = NULL;
1440   GError **error = &local_error;
1441   GSubprocessLauncher *launcher;
1442   GSubprocess *proc;
1443   GPtrArray *args;
1444   GInputStream *stdout_stream;
1445   gchar *result;
1446   gchar **split;
1447
1448   g_setenv ("TEST_ENV_INHERIT1", "1", TRUE);
1449   g_setenv ("TEST_ENV_INHERIT2", "2", TRUE);
1450
1451   args = get_test_subprocess_args ("env", NULL);
1452   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1453   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1454   g_subprocess_launcher_set_environ (launcher, NULL);
1455   g_subprocess_launcher_setenv (launcher, "TWO", "2", TRUE);
1456   g_subprocess_launcher_unsetenv (launcher, "TEST_ENV_INHERIT1");
1457
1458   g_assert_null (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT1"));
1459   g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TEST_ENV_INHERIT2"), ==, "2");
1460   g_assert_cmpstr (g_subprocess_launcher_getenv (launcher, "TWO"), ==, "2");
1461
1462   proc = g_subprocess_launcher_spawn (launcher, error, args->pdata[0], "env", NULL);
1463   g_ptr_array_free (args, TRUE);
1464   g_assert_no_error (local_error);
1465
1466   stdout_stream = g_subprocess_get_stdout_pipe (proc);
1467
1468   result = splice_to_string (stdout_stream, error);
1469   split = g_strsplit (result, LINEEND, -1);
1470   g_assert_null (g_environ_getenv (split, "TEST_ENV_INHERIT1"));
1471   g_assert_cmpstr (g_environ_getenv (split, "TEST_ENV_INHERIT2"), ==, "2");
1472   g_assert_cmpstr (g_environ_getenv (split, "TWO"), ==, "2");
1473
1474   g_strfreev (split);
1475   g_free (result);
1476   g_object_unref (proc);
1477   g_object_unref (launcher);
1478 }
1479
1480 static void
1481 test_cwd (void)
1482 {
1483   GError *local_error = NULL;
1484   GSubprocessLauncher *launcher;
1485   GSubprocess *proc;
1486   GPtrArray *args;
1487   GInputStream *stdout_stream;
1488   gchar *result;
1489   gsize result_len;
1490   const gchar *tmpdir = g_get_tmp_dir ();
1491   gchar *tmpdir_basename = NULL, *result_basename = NULL;
1492
1493   args = get_test_subprocess_args ("cwd", NULL);
1494   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1495   g_subprocess_launcher_set_flags (launcher, G_SUBPROCESS_FLAGS_STDOUT_PIPE);
1496   g_subprocess_launcher_set_cwd (launcher, tmpdir);
1497
1498   proc = g_subprocess_launcher_spawnv (launcher, (const char * const *)args->pdata, &local_error);
1499   g_ptr_array_free (args, TRUE);
1500   g_assert_no_error (local_error);
1501
1502   stdout_stream = g_subprocess_get_stdout_pipe (proc);
1503
1504   result = splice_to_string (stdout_stream, &local_error);
1505   g_assert_no_error (local_error);
1506   result_len = strlen (result);
1507
1508   /* The result should end with a line ending */
1509   g_assert_cmpstr (result + result_len - strlen (LINEEND), ==, LINEEND);
1510
1511   /* Not sure if the testprog guarantees to return an absolute path for the cwd,
1512    * so only compare the basenames. */
1513   tmpdir_basename = g_path_get_basename (tmpdir);
1514   result_basename = g_path_get_basename (g_strstrip (result));
1515   g_assert_cmpstr (tmpdir_basename, ==, result_basename);
1516   g_free (tmpdir_basename);
1517   g_free (result_basename);
1518
1519   g_free (result);
1520   g_object_unref (proc);
1521   g_object_unref (launcher);
1522 }
1523 #ifdef G_OS_UNIX
1524
1525 static void
1526 test_subprocess_launcher_close (void)
1527 {
1528   GError *local_error = NULL;
1529   GError **error = &local_error;
1530   GSubprocessLauncher *launcher;
1531   GSubprocess *proc;
1532   GPtrArray *args;
1533   int fd, fd2;
1534   gboolean is_open;
1535
1536   /* Open two arbitrary FDs. One of them, @fd, will be transferred to the
1537    * launcher, and the other’s FD integer will be used as its target FD, giving
1538    * the mapping `fd â†’ fd2` if a child process were to be spawned.
1539    *
1540    * The launcher will then be closed, which should close @fd but *not* @fd2,
1541    * as the value of @fd2 is only valid as an FD in a child process. (A child
1542    * process is not actually spawned in this test.)
1543    */
1544   fd = dup (0);
1545   fd2 = dup (0);
1546   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
1547   g_subprocess_launcher_take_fd (launcher, fd, fd2);
1548
1549   is_open = fcntl (fd, F_GETFD) != -1;
1550   g_assert_true (is_open);
1551   is_open = fcntl (fd2, F_GETFD) != -1;
1552   g_assert_true (is_open);
1553
1554   g_subprocess_launcher_close (launcher);
1555
1556   is_open = fcntl (fd, F_GETFD) != -1;
1557   g_assert_false (is_open);
1558   is_open = fcntl (fd2, F_GETFD) != -1;
1559   g_assert_true (is_open);
1560
1561   /* Now test that actually trying to spawn the child gives %G_IO_ERROR_CLOSED,
1562    * as g_subprocess_launcher_close() has been called. */
1563   args = get_test_subprocess_args ("cat", NULL);
1564   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1565   g_ptr_array_free (args, TRUE);
1566   g_assert_null (proc);
1567   g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_CLOSED);
1568   g_clear_error (error);
1569
1570   close (fd2);
1571   g_object_unref (launcher);
1572 }
1573
1574 static void
1575 test_stdout_file (void)
1576 {
1577   GError *local_error = NULL;
1578   GError **error = &local_error;
1579   GSubprocessLauncher *launcher;
1580   GSubprocess *proc;
1581   GPtrArray *args;
1582   GFile *tmpfile;
1583   GFileIOStream *iostream;
1584   GOutputStream *stdin_stream;
1585   const char *test_data = "this is some test data\n";
1586   char *tmp_contents;
1587   char *tmp_file_path;
1588
1589   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1590   g_assert_no_error (local_error);
1591   g_clear_object (&iostream);
1592
1593   tmp_file_path = g_file_get_path (tmpfile);
1594
1595   args = get_test_subprocess_args ("cat", NULL);
1596   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1597   g_subprocess_launcher_set_stdout_file_path (launcher, tmp_file_path);
1598   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1599   g_ptr_array_free (args, TRUE);
1600   g_assert_no_error (local_error);
1601
1602   stdin_stream = g_subprocess_get_stdin_pipe (proc);
1603
1604   g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1605   g_assert_no_error (local_error);
1606
1607   g_output_stream_close (stdin_stream, NULL, error);
1608   g_assert_no_error (local_error);
1609
1610   g_subprocess_wait_check (proc, NULL, error);
1611
1612   g_object_unref (launcher);
1613   g_object_unref (proc);
1614
1615   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1616   g_assert_no_error (local_error);
1617
1618   g_assert_cmpstr (test_data, ==, tmp_contents);
1619   g_free (tmp_contents);
1620
1621   (void) g_file_delete (tmpfile, NULL, NULL);
1622   g_object_unref (tmpfile);
1623   g_free (tmp_file_path);
1624 }
1625
1626 static void
1627 test_stdout_fd (void)
1628 {
1629   GError *local_error = NULL;
1630   GError **error = &local_error;
1631   GSubprocessLauncher *launcher;
1632   GSubprocess *proc;
1633   GPtrArray *args;
1634   GFile *tmpfile;
1635   GFileIOStream *iostream;
1636   GFileDescriptorBased *descriptor_stream;
1637   GOutputStream *stdin_stream;
1638   const char *test_data = "this is some test data\n";
1639   char *tmp_contents;
1640
1641   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1642   g_assert_no_error (local_error);
1643
1644   args = get_test_subprocess_args ("cat", NULL);
1645   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1646   descriptor_stream = G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream)));
1647   g_subprocess_launcher_take_stdout_fd (launcher, dup (g_file_descriptor_based_get_fd (descriptor_stream)));
1648   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1649   g_ptr_array_free (args, TRUE);
1650   g_assert_no_error (local_error);
1651
1652   g_clear_object (&iostream);
1653
1654   stdin_stream = g_subprocess_get_stdin_pipe (proc);
1655
1656   g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1657   g_assert_no_error (local_error);
1658
1659   g_output_stream_close (stdin_stream, NULL, error);
1660   g_assert_no_error (local_error);
1661
1662   g_subprocess_wait_check (proc, NULL, error);
1663
1664   g_object_unref (launcher);
1665   g_object_unref (proc);
1666
1667   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1668   g_assert_no_error (local_error);
1669
1670   g_assert_cmpstr (test_data, ==, tmp_contents);
1671   g_free (tmp_contents);
1672
1673   (void) g_file_delete (tmpfile, NULL, NULL);
1674   g_object_unref (tmpfile);
1675 }
1676
1677 static void
1678 child_setup (gpointer user_data)
1679 {
1680   dup2 (GPOINTER_TO_INT (user_data), 1);
1681 }
1682
1683 static void
1684 test_child_setup (void)
1685 {
1686   GError *local_error = NULL;
1687   GError **error = &local_error;
1688   GSubprocessLauncher *launcher;
1689   GSubprocess *proc;
1690   GPtrArray *args;
1691   GFile *tmpfile;
1692   GFileIOStream *iostream;
1693   GOutputStream *stdin_stream;
1694   const char *test_data = "this is some test data\n";
1695   char *tmp_contents;
1696   int fd;
1697
1698   tmpfile = g_file_new_tmp ("gsubprocessXXXXXX", &iostream, error);
1699   g_assert_no_error (local_error);
1700
1701   fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (g_io_stream_get_output_stream (G_IO_STREAM (iostream))));
1702
1703   args = get_test_subprocess_args ("cat", NULL);
1704   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE);
1705   g_subprocess_launcher_set_child_setup (launcher, child_setup, GINT_TO_POINTER (fd), NULL);
1706   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1707   g_ptr_array_free (args, TRUE);
1708   g_assert_no_error (local_error);
1709
1710   g_clear_object (&iostream);
1711
1712   stdin_stream = g_subprocess_get_stdin_pipe (proc);
1713
1714   g_output_stream_write_all (stdin_stream, test_data, strlen (test_data), NULL, NULL, error);
1715   g_assert_no_error (local_error);
1716
1717   g_output_stream_close (stdin_stream, NULL, error);
1718   g_assert_no_error (local_error);
1719
1720   g_subprocess_wait_check (proc, NULL, error);
1721
1722   g_object_unref (launcher);
1723   g_object_unref (proc);
1724
1725   g_file_load_contents (tmpfile, NULL, &tmp_contents, NULL, NULL, error);
1726   g_assert_no_error (local_error);
1727
1728   g_assert_cmpstr (test_data, ==, tmp_contents);
1729   g_free (tmp_contents);
1730
1731   (void) g_file_delete (tmpfile, NULL, NULL);
1732   g_object_unref (tmpfile);
1733 }
1734
1735 static void
1736 do_test_pass_fd (GSubprocessFlags     flags,
1737                  GSpawnChildSetupFunc child_setup)
1738 {
1739   GError *local_error = NULL;
1740   GError **error = &local_error;
1741   GInputStream *child_input;
1742   GDataInputStream *child_datainput;
1743   GSubprocessLauncher *launcher;
1744   GSubprocess *proc;
1745   GPtrArray *args;
1746   int basic_pipefds[2];
1747   int needdup_pipefds[2];
1748   char *buf;
1749   gsize len;
1750   char *basic_fd_str;
1751   char *needdup_fd_str;
1752
1753   g_unix_open_pipe (basic_pipefds, O_CLOEXEC, error);
1754   g_assert_no_error (local_error);
1755   g_unix_open_pipe (needdup_pipefds, O_CLOEXEC, error);
1756   g_assert_no_error (local_error);
1757
1758   basic_fd_str = g_strdup_printf ("%d", basic_pipefds[1]);
1759   needdup_fd_str = g_strdup_printf ("%d", needdup_pipefds[1] + 1);
1760
1761   args = get_test_subprocess_args ("write-to-fds", basic_fd_str, needdup_fd_str, NULL);
1762   launcher = g_subprocess_launcher_new (flags);
1763   g_subprocess_launcher_take_fd (launcher, basic_pipefds[1], basic_pipefds[1]);
1764   g_subprocess_launcher_take_fd (launcher, needdup_pipefds[1], needdup_pipefds[1] + 1);
1765   if (child_setup != NULL)
1766     g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL);
1767   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error);
1768   g_ptr_array_free (args, TRUE);
1769   g_assert_no_error (local_error);
1770
1771   g_free (basic_fd_str);
1772   g_free (needdup_fd_str);
1773
1774   child_input = g_unix_input_stream_new (basic_pipefds[0], TRUE);
1775   child_datainput = g_data_input_stream_new (child_input);
1776   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1777   g_assert_no_error (local_error);
1778   g_assert_cmpstr (buf, ==, "hello world");
1779   g_object_unref (child_datainput);
1780   g_object_unref (child_input);
1781   g_free (buf);
1782
1783   child_input = g_unix_input_stream_new (needdup_pipefds[0], TRUE);
1784   child_datainput = g_data_input_stream_new (child_input);
1785   buf = g_data_input_stream_read_line_utf8 (child_datainput, &len, NULL, error);
1786   g_assert_no_error (local_error);
1787   g_assert_cmpstr (buf, ==, "hello world");
1788   g_free (buf);
1789   g_object_unref (child_datainput);
1790   g_object_unref (child_input);
1791
1792   g_object_unref (launcher);
1793   g_object_unref (proc);
1794 }
1795
1796 static void
1797 test_pass_fd (void)
1798 {
1799   do_test_pass_fd (G_SUBPROCESS_FLAGS_NONE, NULL);
1800 }
1801
1802 static void
1803 empty_child_setup (gpointer user_data)
1804 {
1805 }
1806
1807 static void
1808 test_pass_fd_empty_child_setup (void)
1809 {
1810   /* Using a child setup function forces gspawn to use fork/exec
1811    * rather than posix_spawn.
1812    */
1813   do_test_pass_fd (G_SUBPROCESS_FLAGS_NONE, empty_child_setup);
1814 }
1815
1816 static void
1817 test_pass_fd_inherit_fds (void)
1818 {
1819   /* Try to test the optimized posix_spawn codepath instead of
1820    * fork/exec. Currently this requires using INHERIT_FDS since gspawn's
1821    * posix_spawn codepath does not currently handle closing
1822    * non-inherited fds. Note that using INHERIT_FDS means our testing of
1823    * g_subprocess_launcher_take_fd() is less-comprehensive than when
1824    * using G_SUBPROCESS_FLAGS_NONE.
1825    */
1826   do_test_pass_fd (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL);
1827 }
1828
1829 static void
1830 do_test_fd_conflation (GSubprocessFlags     flags,
1831                        GSpawnChildSetupFunc child_setup,
1832                        gboolean             test_child_err_report_fd)
1833 {
1834   char success_message[] = "Yay success!";
1835   GError *error = NULL;
1836   GOutputStream *output_stream;
1837   GSubprocessLauncher *launcher;
1838   GSubprocess *proc;
1839   GPtrArray *args;
1840   int unused_pipefds[2];
1841   int pipefds[2];
1842   int fd_to_pass_to_child;
1843   gsize bytes_written;
1844   gboolean success;
1845   char *fd_str;
1846
1847   /* This test must run in a new process because it is extremely sensitive to
1848    * order of opened fds.
1849    */
1850   if (!g_test_subprocess ())
1851     {
1852       g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR);
1853       g_test_trap_assert_passed ();
1854       return;
1855     }
1856
1857   g_unix_open_pipe (unused_pipefds, O_CLOEXEC, &error);
1858   g_assert_no_error (error);
1859
1860   g_unix_open_pipe (pipefds, O_CLOEXEC, &error);
1861   g_assert_no_error (error);
1862
1863   /* The fds should be sequential since we are in a new process. */
1864   g_assert_cmpint (unused_pipefds[0] /* 3 */, ==, unused_pipefds[1] - 1);
1865   g_assert_cmpint (unused_pipefds[1] /* 4 */, ==, pipefds[0] - 1);
1866   g_assert_cmpint (pipefds[0] /* 5 */, ==, pipefds[1] /* 6 */ - 1);
1867
1868   /* Because GSubprocess allows arbitrary remapping of fds, it has to be careful
1869    * to avoid fd conflation issues, e.g. it should properly handle 5 -> 4 and
1870    * 4 -> 5 at the same time. GIO previously attempted to handle this by naively
1871    * dup'ing the source fds, but this was not good enough because it was
1872    * possible that the dup'ed result could still conflict with one of the target
1873    * fds. For example:
1874    *
1875    * source_fd 5 -> target_fd 9, source_fd 3 -> target_fd 7
1876    *
1877    * dup(5) -> dup returns 8
1878    * dup(3) -> dup returns 9
1879    *
1880    * After dup'ing, we wind up with: 8 -> 9, 9 -> 7. That means that after we
1881    * dup2(8, 9), we have clobbered fd 9 before we dup2(9, 7). The end result is
1882    * we have remapped 5 -> 9 as expected, but then remapped 5 -> 7 instead of
1883    * 3 -> 7 as the application intended.
1884    *
1885    * This issue has been fixed in the simplest way possible, by passing a
1886    * minimum fd value when using F_DUPFD_CLOEXEC that is higher than any of the
1887    * target fds, to guarantee all source fds are different than all target fds,
1888    * eliminating any possibility of conflation.
1889    *
1890    * Anyway, that is why we have the unused_pipefds here. We need to open fds in
1891    * a certain order in order to trick older GSubprocess into conflating the
1892    * fds. The primary goal of this test is to ensure this particular conflation
1893    * issue is not reintroduced. See glib#2503.
1894    *
1895    * This test also has an alternate mode of operation where it instead tests
1896    * for conflation with gspawn's child_err_report_fd, glib#2506.
1897    *
1898    * Be aware this test is necessarily extremely fragile. To reproduce these
1899    * bugs, it relies on internals of gspawn and gmain that will likely change
1900    * in the future, eventually causing this test to no longer test the bugs
1901    * it was originally designed to test. That is OK! If the test fails, at
1902    * least you know *something* is wrong.
1903    */
1904   if (test_child_err_report_fd)
1905     fd_to_pass_to_child = pipefds[1] + 2 /* 8 */;
1906   else
1907     fd_to_pass_to_child = pipefds[1] + 3 /* 9 */;
1908
1909   launcher = g_subprocess_launcher_new (flags);
1910   g_subprocess_launcher_take_fd (launcher, pipefds[0] /* 5 */, fd_to_pass_to_child);
1911   g_subprocess_launcher_take_fd (launcher, unused_pipefds[0] /* 3 */, pipefds[1] + 1 /* 7 */);
1912   if (child_setup != NULL)
1913     g_subprocess_launcher_set_child_setup (launcher, child_setup, NULL, NULL);
1914   fd_str = g_strdup_printf ("%d", fd_to_pass_to_child);
1915   args = get_test_subprocess_args ("read-from-fd", fd_str, NULL);
1916   proc = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, &error);
1917   g_assert_no_error (error);
1918   g_assert_nonnull (proc);
1919   g_ptr_array_free (args, TRUE);
1920   g_object_unref (launcher);
1921   g_free (fd_str);
1922
1923   /* Close the read ends of the pipes. */
1924   close (unused_pipefds[0]);
1925   close (pipefds[0]);
1926
1927   /* Also close the write end of the unused pipe. */
1928   close (unused_pipefds[1]);
1929
1930   /* If doing our normal test:
1931    *
1932    * So now pipefds[0] should be inherited into the subprocess as
1933    * pipefds[1] + 2, and unused_pipefds[0] should be inherited as
1934    * pipefds[1] + 1. We will write to pipefds[1] and the subprocess will verify
1935    * that it reads the expected data. But older broken GIO will accidentally
1936    * clobber pipefds[1] + 2 with pipefds[1] + 1! This will cause the subprocess
1937    * to hang trying to read from the wrong pipe.
1938    *
1939    * If testing conflation with child_err_report_fd:
1940    *
1941    * We are actually already done. The real test succeeded if we made it this
1942    * far without hanging while spawning the child. But let's continue with our
1943    * write and read anyway, to ensure things are good.
1944    */
1945   output_stream = g_unix_output_stream_new (pipefds[1], TRUE);
1946   success = g_output_stream_write_all (output_stream,
1947                                        success_message, sizeof (success_message),
1948                                        &bytes_written,
1949                                        NULL,
1950                                        &error);
1951   g_assert_no_error (error);
1952   g_assert_cmpint (bytes_written, ==, sizeof (success_message));
1953   g_assert_true (success);
1954   g_object_unref (output_stream);
1955
1956   success = g_subprocess_wait_check (proc, NULL, &error);
1957   g_assert_no_error (error);
1958   g_object_unref (proc);
1959 }
1960
1961 static void
1962 test_fd_conflation (void)
1963 {
1964   do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, NULL, FALSE);
1965 }
1966
1967 static void
1968 test_fd_conflation_empty_child_setup (void)
1969 {
1970   /* Using a child setup function forces gspawn to use fork/exec
1971    * rather than posix_spawn.
1972    */
1973   do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, FALSE);
1974 }
1975
1976 static void
1977 test_fd_conflation_inherit_fds (void)
1978 {
1979   /* Try to test the optimized posix_spawn codepath instead of
1980    * fork/exec. Currently this requires using INHERIT_FDS since gspawn's
1981    * posix_spawn codepath does not currently handle closing
1982    * non-inherited fds.
1983    */
1984   do_test_fd_conflation (G_SUBPROCESS_FLAGS_INHERIT_FDS, NULL, FALSE);
1985 }
1986
1987 static void
1988 test_fd_conflation_child_err_report_fd (void)
1989 {
1990   /* Using a child setup function forces gspawn to use fork/exec
1991    * rather than posix_spawn.
1992    */
1993   do_test_fd_conflation (G_SUBPROCESS_FLAGS_NONE, empty_child_setup, TRUE);
1994 }
1995
1996 #ifdef __linux__
1997
1998 /* Handle ptrace events on @main_child, and assert that when it exits, it does
1999  * so with status %EXIT_SUCCESS, rather than signalling. Other than that, this
2000  * just calls %PTRACE_CONT for all trace events. */
2001 static void
2002 trace_children (pid_t main_child)
2003 {
2004   int wstatus;
2005
2006   g_assert_no_errno (waitpid (main_child, &wstatus, 0));
2007   g_assert_no_errno (ptrace (PTRACE_SETOPTIONS, main_child, NULL,
2008                              (PTRACE_O_TRACEFORK |
2009 #ifdef HAVE_PTRACE_O_EXITKILL
2010                               PTRACE_O_EXITKILL |
2011 #endif
2012                               PTRACE_O_TRACEVFORK |
2013                               PTRACE_O_TRACECLONE |
2014                               PTRACE_O_TRACEEXEC)));
2015   g_assert_no_errno (ptrace (PTRACE_CONT, main_child, NULL, 0));
2016
2017   while (TRUE)
2018     {
2019       pid_t pid;
2020       int wstatus;
2021       int stop_signum;
2022       int ptrace_event;
2023
2024       pid = waitpid (-1, &wstatus, 0);
2025       if (pid == -1 && errno == ECHILD)
2026         break;
2027
2028       g_assert_cmpint (errno, ==, 0);
2029       g_assert_cmpint (pid, >=, 0);
2030
2031       if (WIFSTOPPED (wstatus))
2032         stop_signum = WSTOPSIG (wstatus);
2033       else
2034         stop_signum = 0;
2035
2036       switch (stop_signum)
2037         {
2038         case SIGTRAP:
2039           ptrace_event = (wstatus >> 16) & 0xffff;
2040           switch (ptrace_event)
2041             {
2042             case 0:
2043               g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, stop_signum));
2044               break;
2045             default:
2046               g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, 0));
2047               break;
2048             }
2049           break;
2050         case SIGSTOP:
2051           g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, 0));
2052           break;
2053         default:
2054           if (!WIFEXITED (wstatus) && !WIFSIGNALED (wstatus))
2055             g_assert_no_errno (ptrace (PTRACE_CONT, pid, NULL, stop_signum));
2056           break;
2057         }
2058
2059       if (pid == main_child)
2060         {
2061           g_assert_false (WIFSIGNALED (wstatus));
2062           if (WIFEXITED (wstatus))
2063             {
2064               g_assert_cmpint (WEXITSTATUS (wstatus), ==, EXIT_SUCCESS);
2065               break;
2066             }
2067         }
2068     }
2069 }
2070
2071 #endif  /* __linux__ */
2072
2073 static void
2074 test_exit_status_trapped (void)
2075 {
2076 #ifdef __linux__
2077   GPtrArray *args = NULL;
2078   pid_t test_child;
2079 #endif
2080
2081   g_test_summary ("Test that exit status is reported correctly for ptrace()d child processes");
2082   g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3433");
2083
2084 #ifdef __linux__
2085   /* Call fork() directly here, rather than using #GSubprocess, so that we can
2086    * safely call waitpid() on it ourselves without interfering with the internals
2087    * of #GSubprocess.
2088    * See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3433#note_1749055 */
2089   args = get_test_subprocess_args ("sleep-and-kill", NULL);
2090   test_child = fork ();
2091   if (test_child == 0)
2092     {
2093       /* Between fork() and exec() we can only call async-signal-safe functions. */
2094       if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) < 0)
2095         abort ();
2096
2097       g_assert_no_errno (execvp (args->pdata[0], (char * const *) args->pdata));
2098     }
2099
2100   trace_children (test_child);
2101
2102   g_clear_pointer (&args, g_ptr_array_unref);
2103 #else
2104   g_test_skip ("ptrace() support for this test is only tested on Linux");
2105 #endif
2106 }
2107
2108 #endif  /* G_OS_UNIX */
2109
2110 static void
2111 test_launcher_environment (void)
2112 {
2113   GSubprocessLauncher *launcher;
2114   GError *error = NULL;
2115   GSubprocess *proc;
2116   GPtrArray *args;
2117   gchar *out;
2118
2119   g_setenv ("A", "B", TRUE);
2120   g_setenv ("C", "D", TRUE);
2121
2122   launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
2123
2124   /* unset a variable */
2125   g_subprocess_launcher_unsetenv (launcher, "A");
2126
2127   /* and set a different one */
2128   g_subprocess_launcher_setenv (launcher, "E", "F", TRUE);
2129
2130   args = get_test_subprocess_args ("printenv", "A", "C", "E", NULL);
2131   proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &error);
2132   g_assert_no_error (error);
2133   g_assert_nonnull (proc);
2134
2135   g_subprocess_communicate_utf8 (proc, NULL, NULL, &out, NULL, &error);
2136   g_assert_no_error (error);
2137
2138   g_assert_cmpstr (out, ==, "C=D" LINEEND "E=F" LINEEND);
2139   g_free (out);
2140
2141   g_object_unref (proc);
2142   g_object_unref (launcher);
2143   g_ptr_array_unref (args);
2144 }
2145
2146 int
2147 main (int argc, char **argv)
2148 {
2149   const struct
2150     {
2151       const gchar *subtest;
2152       GSubprocessFlags flags;
2153     }
2154   flags_vectors[] =
2155     {
2156       { "", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_MERGE },
2157       { "/no-pipes", G_SUBPROCESS_FLAGS_NONE },
2158       { "/separate-stderr", G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE },
2159       { "/stdout-only", G_SUBPROCESS_FLAGS_STDOUT_PIPE },
2160       { "/stderr-only", G_SUBPROCESS_FLAGS_STDERR_PIPE },
2161       { "/stdout-silence", G_SUBPROCESS_FLAGS_STDOUT_SILENCE },
2162     };
2163   gsize i;
2164
2165   g_test_init (&argc, &argv, NULL);
2166
2167   g_test_add_func ("/gsubprocess/noop", test_noop);
2168   g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null);
2169   g_test_add_func ("/gsubprocess/noop-no-wait", test_noop_no_wait);
2170   g_test_add_func ("/gsubprocess/noop-stdin-inherit", test_noop_stdin_inherit);
2171 #ifdef G_OS_UNIX
2172   g_test_add_func ("/gsubprocess/search-path", test_search_path);
2173   g_test_add_func ("/gsubprocess/search-path-from-envp", test_search_path_from_envp);
2174   g_test_add_func ("/gsubprocess/signal", test_signal);
2175 #endif
2176   g_test_add_func ("/gsubprocess/exit1", test_exit1);
2177   g_test_add_func ("/gsubprocess/exit1/cancel", test_exit1_cancel);
2178   g_test_add_func ("/gsubprocess/exit1/cancel_in_cb", test_exit1_cancel_in_cb);
2179   g_test_add_func ("/gsubprocess/echo1", test_echo1);
2180 #ifdef G_OS_UNIX
2181   g_test_add_func ("/gsubprocess/echo-merged", test_echo_merged);
2182 #endif
2183   g_test_add_func ("/gsubprocess/cat-utf8", test_cat_utf8);
2184   g_test_add_func ("/gsubprocess/cat-eof", test_cat_eof);
2185   g_test_add_func ("/gsubprocess/multi1", test_multi_1);
2186
2187   /* Add various tests for g_subprocess_communicate() with different flags. */
2188   for (i = 0; i < G_N_ELEMENTS (flags_vectors); i++)
2189     {
2190       gchar *test_path = NULL;
2191
2192       test_path = g_strdup_printf ("/gsubprocess/communicate%s", flags_vectors[i].subtest);
2193       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2194                             test_communicate);
2195       g_free (test_path);
2196
2197       test_path = g_strdup_printf ("/gsubprocess/communicate/cancelled%s", flags_vectors[i].subtest);
2198       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2199                             test_communicate_cancelled);
2200       g_free (test_path);
2201
2202       test_path = g_strdup_printf ("/gsubprocess/communicate/async%s", flags_vectors[i].subtest);
2203       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2204                             test_communicate_async);
2205       g_free (test_path);
2206
2207       test_path = g_strdup_printf ("/gsubprocess/communicate/async/cancelled%s", flags_vectors[i].subtest);
2208       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2209                             test_communicate_cancelled_async);
2210       g_free (test_path);
2211
2212       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8%s", flags_vectors[i].subtest);
2213       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2214                             test_communicate_utf8);
2215       g_free (test_path);
2216
2217       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/cancelled%s", flags_vectors[i].subtest);
2218       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2219                             test_communicate_utf8_cancelled);
2220       g_free (test_path);
2221
2222       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async%s", flags_vectors[i].subtest);
2223       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2224                             test_communicate_utf8_async);
2225       g_free (test_path);
2226
2227       test_path = g_strdup_printf ("/gsubprocess/communicate/utf8/async/cancelled%s", flags_vectors[i].subtest);
2228       g_test_add_data_func (test_path, GINT_TO_POINTER (flags_vectors[i].flags),
2229                             test_communicate_utf8_cancelled_async);
2230       g_free (test_path);
2231     }
2232
2233   g_test_add_func ("/gsubprocess/communicate/utf8/async/invalid", test_communicate_utf8_async_invalid);
2234   g_test_add_func ("/gsubprocess/communicate/utf8/invalid", test_communicate_utf8_invalid);
2235   g_test_add_func ("/gsubprocess/communicate/nothing", test_communicate_nothing);
2236   g_test_add_func ("/gsubprocess/terminate", test_terminate);
2237   g_test_add_func ("/gsubprocess/env", test_env);
2238   g_test_add_func ("/gsubprocess/env/inherit", test_env_inherit);
2239   g_test_add_func ("/gsubprocess/cwd", test_cwd);
2240 #ifdef G_OS_UNIX
2241   g_test_add_func ("/gsubprocess/launcher-close", test_subprocess_launcher_close);
2242   g_test_add_func ("/gsubprocess/stdout-file", test_stdout_file);
2243   g_test_add_func ("/gsubprocess/stdout-fd", test_stdout_fd);
2244   g_test_add_func ("/gsubprocess/child-setup", test_child_setup);
2245   g_test_add_func ("/gsubprocess/pass-fd/basic", test_pass_fd);
2246   g_test_add_func ("/gsubprocess/pass-fd/empty-child-setup", test_pass_fd_empty_child_setup);
2247   g_test_add_func ("/gsubprocess/pass-fd/inherit-fds", test_pass_fd_inherit_fds);
2248   g_test_add_func ("/gsubprocess/fd-conflation/basic", test_fd_conflation);
2249   g_test_add_func ("/gsubprocess/fd-conflation/empty-child-setup", test_fd_conflation_empty_child_setup);
2250   g_test_add_func ("/gsubprocess/fd-conflation/inherit-fds", test_fd_conflation_inherit_fds);
2251   g_test_add_func ("/gsubprocess/fd-conflation/child-err-report-fd", test_fd_conflation_child_err_report_fd);
2252   g_test_add_func ("/gsubprocess/exit-status/trapped", test_exit_status_trapped);
2253 #endif
2254   g_test_add_func ("/gsubprocess/launcher-environment", test_launcher_environment);
2255
2256   return g_test_run ();
2257 }