Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit a3664fae9ece396952d732cc937e63192d8c6f76 1 parent 8855c14
Nick Treleaven ntrel authored
Showing with 79 additions and 9 deletions.
  1. +8 −8 src/build.c
  2. +71 −1 src/win32.c
16 src/build.c
View
@@ -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);
72 src/win32.c
View
@@ -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;
Please sign in to comment.
Something went wrong with that request. Please try again.