Add g_spawn_check_exit_status()

Many (if not "almost all") programs that spawn other programs via
g_spawn_sync() or the like simply want to check whether or not the
child exited successfully, but doing so requires use of
platform-specific functionality and there's actually a fair amount of
boilerplate involved.

This new API will help drain a *lot* of mostly duplicated code in
GNOME, from gnome-session to gdm.  And we can see that some bits even
inside GLib were doing it wrong; for example checking the exit status
on Unix, but ignoring it on Windows.

https://bugzilla.gnome.org/show_bug.cgi?id=679691
This commit is contained in:
Colin Walters
2012-07-10 11:27:22 -04:00
parent 82d914d808
commit f7abd3ce13
11 changed files with 161 additions and 67 deletions

View File

@@ -43,7 +43,6 @@
#ifdef G_OS_UNIX
#include <gio/gunixsocketaddress.h>
#include <sys/wait.h>
#endif
#ifdef G_OS_WIN32
@@ -1062,40 +1061,16 @@ get_session_address_dbus_launch (GError **error)
&launch_stderr,
&exit_status,
error))
{
goto out;
}
if (!g_spawn_check_exit_status (exit_status, error))
{
g_prefix_error (error, _("Error spawning command line `%s': "), command_line);
goto out;
}
if (!WIFEXITED (exit_status))
{
gchar *escaped_stderr;
escaped_stderr = g_strescape (launch_stderr, "");
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Abnormal program termination spawning command line `%s': %s"),
command_line,
escaped_stderr);
g_free (escaped_stderr);
goto out;
}
if (WEXITSTATUS (exit_status) != 0)
{
gchar *escaped_stderr;
escaped_stderr = g_strescape (launch_stderr, "");
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Command line `%s' exited with non-zero exit status %d: %s"),
command_line,
WEXITSTATUS (exit_status),
escaped_stderr);
g_free (escaped_stderr);
goto out;
}
/* From the dbus-launch(1) man page:
*
* --binary-syntax Write to stdout a nul-terminated bus address,

View File

@@ -26,7 +26,6 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#ifdef HAVE_CRT_EXTERNS_H
#include <crt_externs.h>
@@ -1850,8 +1849,7 @@ update_program_done (GPid pid,
gpointer data)
{
/* Did the application exit correctly */
if (WIFEXITED (status) &&
WEXITSTATUS (status) == 0)
if (g_spawn_check_exit_status (status, NULL))
{
/* Here we could clean out any caches in use */
}

View File

@@ -33,9 +33,6 @@
#ifdef G_OS_WIN32
#include <io.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <gio/gmemoryoutputstream.h>
#include <gio/gzlibcompressor.h>
@@ -331,14 +328,14 @@ end_element (GMarkupParseContext *context,
g_propagate_error (error, my_error);
goto cleanup;
}
#ifdef HAVE_SYS_WAIT_H
if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
/* Ugly...we shoud probably just let stderr be inherited */
if (!g_spawn_check_exit_status (status, NULL))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Error processing input file with xmllint:\n%s"), stderr_child);
goto cleanup;
}
#endif
g_free (stderr_child);
g_free (real_file);
@@ -387,14 +384,13 @@ end_element (GMarkupParseContext *context,
g_propagate_error (error, my_error);
goto cleanup;
}
#ifdef HAVE_SYS_WAIT_H
if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
if (!g_spawn_check_exit_status (status, NULL))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Error processing input file with to-pixdata:\n%s"), stderr_child);
goto cleanup;
}
#endif
g_free (stderr_child);
g_free (real_file);

View File

@@ -25,9 +25,6 @@
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include "gdbus-tests.h"
@@ -97,10 +94,8 @@ test_connection_flush (void)
&exit_status,
&error);
g_assert_no_error (error);
#ifdef HAVE_SYS_WAIT_H
g_assert (WIFEXITED (exit_status));
g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
#endif
g_spawn_check_exit_status (exit_status, &error);
g_assert_no_error (error);
g_assert (ret);
timeout_mainloop_id = g_timeout_add (1000, test_connection_flush_on_timeout, GUINT_TO_POINTER (n));

View File

@@ -141,7 +141,7 @@ test_connection_life_cycle (void)
*
*/
c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
_g_assert_error_domain (error, G_IO_ERROR);
g_assert (error != NULL);
g_assert (!g_dbus_error_is_remote_error (error));
g_assert (c == NULL);
g_error_free (error);