diff options
author | Colin Walters <walters@verbum.org> | 2012-10-25 02:54:05 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2012-11-04 13:52:31 -0500 |
commit | 0e7ddcade1ae751a793049e0136db79bdc793adf (patch) | |
tree | 1658dc816a4acdf0eb525fe8069de5341569e58c /glib/gspawn.c | |
parent | 05034c0ff1e008ec668197fb4bb01e64b6734849 (diff) | |
download | glib-wip/child-catchall.tar.gz |
GChildWatchSource: Allow passing -1 for pidwip/child-catchall
With the goal of modifying gnome-session to use the new Linux
PR_SET_CHILD_SUBREAPER, it needs to be able to reap arbitary children
that may be reparented to it.
But if gnome-session is going to continue to work with GLib and GIO,
even if we converted all child watches in gnome-session to use this
new API, we'd still have to contend with the possibility of it having
a process spawned indirectly (stuff like the GDBus dbus-launch
invocation). Thus, we don't give the -1 child watch *every* waitpid,
only the ones which don't have a specific watcher.
Also, fix up g_spawn_sync() to hold the unix signal lock when forking.
This way we ensure that GLib itself gets the waitpid() result for the
synchronously spawned child, instead of racing with the worker thread.
https://bugzilla.gnome.org/show_bug.cgi?id=687061
Diffstat (limited to 'glib/gspawn.c')
-rw-r--r-- | glib/gspawn.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/glib/gspawn.c b/glib/gspawn.c index 3545a78ee..1285dd791 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -47,6 +47,7 @@ #include "genviron.h" #include "gmem.h" #include "gmain.h" +#include "gmain-internal.h" #include "gshell.h" #include "gstring.h" #include "gstrfuncs.h" @@ -281,7 +282,7 @@ g_spawn_sync (const gchar *working_directory, gint ret; GString *outstr = NULL; GString *errstr = NULL; - gboolean failed; + gboolean failed = FALSE; gint status; SyncWaitpidData waitpid_data; @@ -300,7 +301,7 @@ g_spawn_sync (const gchar *working_directory, if (standard_error) *standard_error = NULL; - + if (!fork_exec_with_pipes (FALSE, working_directory, argv, @@ -319,11 +320,12 @@ g_spawn_sync (const gchar *working_directory, standard_output ? &outpipe : NULL, standard_error ? &errpipe : NULL, error)) - return FALSE; + { + failed = TRUE; + goto out; + } /* Read data from child. */ - - failed = FALSE; if (outpipe >= 0) { @@ -436,13 +438,14 @@ g_spawn_sync (const gchar *working_directory, g_source_set_callback (source, (GSourceFunc)on_sync_waitpid, &waitpid_data, NULL); g_source_attach (source, context); g_source_unref (source); - + g_main_loop_run (loop); g_main_context_unref (context); g_main_loop_unref (loop); } + out: if (failed) { if (outstr) @@ -1342,7 +1345,10 @@ fork_exec_with_pipes (gboolean intermediate_child, if (standard_error && !make_pipe (stderr_pipe, error)) goto cleanup_and_fail; - pid = fork (); + if (intermediate_child) + pid = fork (); + else + pid = _g_main_fork_and_do_not_reap (); if (pid < 0) { |