From 6c8da69443ee8eee1f06dfdf6a01500d5402a7f3 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 12 Jun 2018 15:41:51 +0100 Subject: [PATCH] gspawn: Make error codes on Windows more specific A slightly modified patch originally written by Morten Welinder to make the error codes returned by g_spawn_*() functions more specific when on Windows. They are already this specific on Linux. Add a unit test for the ENOENT case. https://gitlab.gnome.org/GNOME/glib/issues/303 Signed-off-by: Philip Withnall --- glib/gspawn-win32-helper.c | 7 ++++++- glib/gspawn-win32.c | 9 ++++++++- glib/tests/spawn-singlethread.c | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/glib/gspawn-win32-helper.c b/glib/gspawn-win32-helper.c index 360f47ebb..045d90f71 100644 --- a/glib/gspawn-win32-helper.c +++ b/glib/gspawn-win32-helper.c @@ -352,7 +352,12 @@ main (int ignored_argc, char **ignored_argv) saved_errno = errno; if (handle == -1 && saved_errno != 0) - write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED); + { + int ec = (saved_errno == ENOENT) + ? CHILD_SPAWN_NOENT + : CHILD_SPAWN_FAILED; + write_err_and_exit (child_err_report_fd, ec); + } write (child_err_report_fd, &no_error, sizeof (no_error)); write (child_err_report_fd, &handle, sizeof (handle)); diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c index 7b2451161..0f5b8d034 100644 --- a/glib/gspawn-win32.c +++ b/glib/gspawn-win32.c @@ -46,6 +46,7 @@ #include "glib-private.h" #include "gprintfint.h" #include "glibintl.h" +#include "gspawn-private.h" #include "gthread.h" #include @@ -86,6 +87,7 @@ enum CHILD_NO_ERROR, CHILD_CHDIR_FAILED, CHILD_SPAWN_FAILED, + CHILD_SPAWN_NOENT, }; enum { @@ -374,6 +376,11 @@ set_child_error (gintptr report[2], _("Failed to execute child process (%s)"), g_strerror (report[1])); break; + case CHILD_SPAWN_NOENT: + g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT, + _("Failed to execute child process (%s)"), + g_strerror (report[1])); + break; default: g_assert_not_reached (); } @@ -489,7 +496,7 @@ do_spawn_directly (gint *exit_status, if (rc == -1 && errsv != 0) { - g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, + g_set_error (error, G_SPAWN_ERROR, _g_spawn_exec_err_to_g_error (errsv), _("Failed to execute child process (%s)"), g_strerror (errsv)); return FALSE; diff --git a/glib/tests/spawn-singlethread.c b/glib/tests/spawn-singlethread.c index 7985eef7f..6a07df736 100644 --- a/glib/tests/spawn-singlethread.c +++ b/glib/tests/spawn-singlethread.c @@ -200,6 +200,28 @@ test_spawn_script (void) g_ptr_array_free (argv, TRUE); } +/* Test that spawning a non-existent executable returns %G_SPAWN_ERROR_NOENT. */ +static void +test_spawn_nonexistent (void) +{ + GError *error = NULL; + GPtrArray *argv = NULL; + gchar *stdout_str = NULL; + gint exit_status = -1; + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, "this does not exist"); + g_ptr_array_add (argv, NULL); + + g_spawn_sync (NULL, (char**) argv->pdata, NULL, 0, NULL, NULL, &stdout_str, + NULL, &exit_status, &error); + g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT); + g_assert_null (stdout_str); + g_assert_cmpint (exit_status, ==, -1); + + g_ptr_array_free (argv, TRUE); +} + int main (int argc, char *argv[]) @@ -230,6 +252,7 @@ main (int argc, g_test_add_func ("/gthread/spawn-single-sync", test_spawn_sync); g_test_add_func ("/gthread/spawn-single-async", test_spawn_async); g_test_add_func ("/gthread/spawn-script", test_spawn_script); + g_test_add_func ("/gthread/spawn/nonexistent", test_spawn_nonexistent); ret = g_test_run(); -- 2.11.4.GIT