[geany/geany] a3664f: Fix spawning [synchronous] commands on Windows

Nick Treleaven git-noreply at geany.org
Wed Oct 24 16:35:19 UTC 2012


Branch:      refs/heads/master
Author:      Nick Treleaven <nick.treleaven at btinternet.com>
Committer:   Nick Treleaven <nick.treleaven at btinternet.com>
Date:        Wed, 24 Oct 2012 16:35:19
Commit:      a3664fae9ece396952d732cc937e63192d8c6f76
             https://github.com/geany/geany/commit/a3664fae9ece396952d732cc937e63192d8c6f76

Log Message:
-----------
Fix spawning [synchronous] commands on Windows

Build command spawning failed sometimes when there were several
pages of errors. In these cases the process would block for 30s and
then abort. (Some hangs were also experienced).

This fix does cause a console window to be shown for the duration of
the spawned process. This seems acceptable compared with the old
broken behaviour, and can be useful to abort the build command by
closing the console window.

Note: If 'env' is passed, the old broken spawning is used.


Modified Paths:
--------------
    src/build.c
    src/win32.c

Modified: src/build.c
16 files changed, 8 insertions(+), 8 deletions(-)
===================================================================
@@ -498,7 +498,7 @@ static GeanyBuildCommand *get_build_group(const GeanyBuildSource src, const Gean
  * If any parameter is out of range does nothing.
  *
  * Updates the menu.
- * 
+ *
  **/
 void build_remove_menu_item(const GeanyBuildSource src, const GeanyBuildGroup grp, const gint cmd)
 {
@@ -560,12 +560,12 @@ GeanyBuildCommand *build_get_menu_item(GeanyBuildSource src, GeanyBuildGroup grp
  *         This is a pointer to an internal structure and must not be freed.
  *
  **/
-const gchar *build_get_current_menu_item(const GeanyBuildGroup grp, const guint cmd, 
+const gchar *build_get_current_menu_item(const GeanyBuildGroup grp, const guint cmd,
                                          const GeanyBuildCmdEntries fld)
 {
 	GeanyBuildCommand *c;
 	gchar *str = NULL;
-	
+
 	g_return_val_if_fail(grp < GEANY_GBG_COUNT, NULL);
 	g_return_val_if_fail(fld < GEANY_BC_CMDENTRIES_COUNT, NULL);
 	g_return_val_if_fail(cmd < build_groups_count[grp], NULL);
@@ -593,19 +593,19 @@ const gchar *build_get_current_menu_item(const GeanyBuildGroup grp, const guint
  *
  * Set the specified field of the command specified by @a src, @a grp and @a cmd.
  *
- * @param src the source of the menu item 
+ * @param src the source of the menu item
  * @param grp the group of the specified menu item.
  * @param cmd the index of the menu item within the group.
  * @param fld the field in the menu item command to set
  * @param val the value to set the field to, is copied
  *
  **/
- 
-void build_set_menu_item(const GeanyBuildSource src, const GeanyBuildGroup grp, 
+
+void build_set_menu_item(const GeanyBuildSource src, const GeanyBuildGroup grp,
                          const guint cmd, const GeanyBuildCmdEntries fld, const gchar *val)
 {
 	GeanyBuildCommand **g;
-	
+
 	g_return_if_fail(src < GEANY_BCS_COUNT);
 	g_return_if_fail(grp < GEANY_GBG_COUNT);
 	g_return_if_fail(fld < GEANY_BC_CMDENTRIES_COUNT);
@@ -827,7 +827,7 @@ static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *d
 			&(build_info.pid), NULL, &stdout_fd, &stderr_fd, &error))
 #endif
 	{
-		geany_debug("g_spawn_async_with_pipes() failed: %s", error->message);
+		geany_debug("build command spawning failed: %s", error->message);
 		ui_set_statusbar(TRUE, _("Process failed (%s)"), error->message);
 		g_strfreev(argv);
 		g_error_free(error);


Modified: src/win32.c
72 files changed, 71 insertions(+), 1 deletions(-)
===================================================================
@@ -40,6 +40,7 @@
 #include <math.h>
 #include <stdlib.h>
 
+#include <glib/gstdio.h>
 #include <gdk/gdkwin32.h>
 
 #include "win32.h"
@@ -820,9 +821,28 @@ gchar *win32_get_hostname(void)
 }
 
 
+static gchar *create_temp_file(void)
+{
+	gchar *name;
+	gint fd;
+
+	fd = g_file_open_tmp("tmp_XXXXXX", &name, NULL);
+	if (fd == -1)
+		name = NULL;
+	else
+		close(fd);
+
+	return name;
+}
+
+
+/* Sometimes this blocks for 30s before aborting when there are several
+ * pages of (error) output and sometimes hangs - see the FIXME.
+ * Also gw_spawn.dwExitCode seems to be not set properly. */
 /* Process spawning implementation for Windows, by Pierre Joye.
  * Don't call this function directly, use utils_spawn_[a]sync() instead. */
-gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+static
+gboolean _broken_win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
 					 gchar **std_out, gchar **std_err, gint *exit_status, GError **error)
 {
 	TCHAR  buffer[CMDSIZE]=TEXT("");
@@ -980,6 +1000,56 @@ gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags fl
 }
 
 
+/* Simple replacement for _broken_win32_spawn().
+ * flags is ignored, G_SPAWN_SEARCH_PATH is implied.
+ * Don't call this function directly, use utils_spawn_[a]sync() instead.
+ * Adapted from tm_workspace_create_global_tags(). */
+gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
+					 gchar **std_out, gchar **std_err, gint *exit_status, GError **error)
+{
+	gint ret;
+	gboolean fail;
+	gchar *tmp_file = create_temp_file();
+	gchar *tmp_errfile = create_temp_file();
+	gchar *command;
+
+	if (env != NULL)
+	{
+		return _broken_win32_spawn(dir, argv, env, flags, std_out, std_err,
+			exit_status, error);
+	}
+	if (!tmp_file || !tmp_errfile)
+	{
+		g_warning("%s: Could not create temporary files!", G_STRFUNC);
+		return FALSE;
+	}
+	command = g_strjoinv(" ", argv);
+	SETPTR(command, g_strdup_printf("%s >%s 2>%s",
+		command, tmp_file, tmp_errfile));
+	g_chdir(dir);
+	ret = system(command);
+	/* the command can return -1 as an exit code, so check errno also */
+	fail = ret == -1 && errno;
+	if (!fail)
+	{
+		g_file_get_contents(tmp_file, std_out, NULL, NULL);
+		g_file_get_contents(tmp_errfile, std_err, NULL, NULL);
+	}
+	else if (error)
+		g_set_error_literal(error, G_SPAWN_ERROR, errno, g_strerror(errno));
+
+	g_free(command);
+	g_unlink(tmp_file);
+	g_free(tmp_file);
+	g_unlink(tmp_errfile);
+	g_free(tmp_errfile);
+	if (exit_status)
+		*exit_status = ret;
+
+	return !fail;
+}
+
+
 static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error)
 {
 	DWORD filesize;



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: TBD).


More information about the Commits mailing list