diff options
Diffstat (limited to 'core/glib2/partially-revert-ce0022933c255313e010b27f977f4ae02aad1e7e.patch')
-rw-r--r-- | core/glib2/partially-revert-ce0022933c255313e010b27f977f4ae02aad1e7e.patch | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/core/glib2/partially-revert-ce0022933c255313e010b27f977f4ae02aad1e7e.patch b/core/glib2/partially-revert-ce0022933c255313e010b27f977f4ae02aad1e7e.patch new file mode 100644 index 000000000..f623c1b21 --- /dev/null +++ b/core/glib2/partially-revert-ce0022933c255313e010b27f977f4ae02aad1e7e.patch @@ -0,0 +1,132 @@ +From f3b1054b0ebb4912f700e08da0c3d35c30113e79 Mon Sep 17 00:00:00 2001 +From: Ryan Lortie <desrt@desrt.ca> +Date: Tue, 23 Apr 2013 17:26:48 +0000 +Subject: Partially revert "Merge waitpid() from g_spawn_sync into gmain()" + +This partially reverts commit ce0022933c255313e010b27f977f4ae02aad1e7e. + +It used to be safe to use g_spawn_sync() from processes that had their +own SIGCHLD handler because it simply called wait(). When it was +changed to depend on the GLib child watching infrastructure this meant +that GLib had to own the SIGCHLD handler. + +This caused hangs in at least Pidgin. + +The patch contained two other improvements to the child watch code which +we want to keep, so only revert the changes to gspawn itself. + +https://bugzilla.gnome.org/show_bug.cgi?id=698081 +--- +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 381ed5c..01cedf6 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -47,7 +47,6 @@ + + #include "genviron.h" + #include "gmem.h" +-#include "gmain.h" + #include "gshell.h" + #include "gstring.h" + #include "gstrfuncs.h" +@@ -207,21 +206,6 @@ read_data (GString *str, + } + } + +-typedef struct { +- GMainLoop *loop; +- gint *status_p; +-} SyncWaitpidData; +- +-static void +-on_sync_waitpid (GPid pid, +- gint status, +- gpointer user_data) +-{ +- SyncWaitpidData *data = user_data; +- *(data->status_p) = status; +- g_main_loop_quit (data->loop); +-} +- + /** + * g_spawn_sync: + * @working_directory: (allow-none): child's current working directory, or %NULL to inherit parent's +@@ -277,7 +261,6 @@ g_spawn_sync (const gchar *working_directory, + GString *errstr = NULL; + gboolean failed; + gint status; +- SyncWaitpidData waitpid_data; + + g_return_val_if_fail (argv != NULL, FALSE); + g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE); +@@ -410,32 +393,45 @@ g_spawn_sync (const gchar *working_directory, + close_and_invalidate (&outpipe); + if (errpipe >= 0) + close_and_invalidate (&errpipe); +- +- /* Now create a temporary main context and loop, with just one +- * waitpid source. We used to invoke waitpid() directly here, but +- * this way we unify with the worker thread in gmain.c. ++ ++ /* Wait for child to exit, even if we have ++ * an error pending. + */ +- { +- GMainContext *context; +- GMainLoop *loop; +- GSource *source; +- +- context = g_main_context_new (); +- loop = g_main_loop_new (context, TRUE); ++ again: ++ ++ ret = waitpid (pid, &status, 0); + +- waitpid_data.loop = loop; +- waitpid_data.status_p = &status; +- +- source = g_child_watch_source_new (pid); +- 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); ++ if (ret < 0) ++ { ++ if (errno == EINTR) ++ goto again; ++ else if (errno == ECHILD) ++ { ++ if (exit_status) ++ { ++ g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but ECHILD was received by waitpid(). Most likely the process is ignoring SIGCHLD, or some other thread is invoking waitpid() with a nonpositive first argument; either behavior can break applications that use g_spawn_sync either directly or indirectly."); ++ } ++ else ++ { ++ /* We don't need the exit status. */ ++ } ++ } ++ else ++ { ++ if (!failed) /* avoid error pileups */ ++ { ++ int errsv = errno; + +- g_main_context_unref (context); +- g_main_loop_unref (loop); +- } ++ failed = TRUE; ++ ++ g_set_error (error, ++ G_SPAWN_ERROR, ++ G_SPAWN_ERROR_READ, ++ _("Unexpected error in waitpid() (%s)"), ++ g_strerror (errsv)); ++ } ++ } ++ } + + if (failed) + { +-- +cgit v0.9.1 |