[glib: 2/4] gspawn: Make error codes on Windows more specific



commit 6c8da69443ee8eee1f06dfdf6a01500d5402a7f3
Author: Philip Withnall <withnall endlessm com>
Date:   Tue Jun 12 15:41:51 2018 +0100

    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>

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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]