gspawn: Make error codes on Windows more specific

A slightly modified patch originally written by Morten Welinder
<terra@gnome.org> 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 <withnall@endlessm.com>
This commit is contained in:
Philip Withnall 2018-06-12 15:41:51 +01:00
parent f4d2051fc1
commit 6c8da69443
3 changed files with 37 additions and 2 deletions

View File

@ -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));

View File

@ -46,6 +46,7 @@
#include "glib-private.h"
#include "gprintfint.h"
#include "glibintl.h"
#include "gspawn-private.h"
#include "gthread.h"
#include <string.h>
@ -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;

View File

@ -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();