[geany/geany] 690cb9: Alter build.c to use the new spawning module
Dimitar Zhekov
git-noreply at xxxxx
Fri May 15 17:07:21 UTC 2015
Branch: refs/heads/master
Author: Dimitar Zhekov <dimitar.zhekov at gmail.com>
Committer: Dimitar Zhekov <dimitar.zhekov at gmail.com>
Date: Sat, 14 Mar 2015 19:36:05 UTC
Commit: 690cb922be902f023881d455ae0c0a87d1c62170
https://github.com/geany/geany/commit/690cb922be902f023881d455ae0c0a87d1c62170
Log Message:
-----------
Alter build.c to use the new spawning module
The wrong and misleading "Failed to change the working directory" is
changed to a generic "Invalid working directory".
Under Windows, the build commands are run directly as command lines,
while under Unix, /bin/sh is used - for compatibility, and because
that's probably what a *nix user expects.
The run script is always run as a command line, since it contains it's
own shell, and because that lets us specify %c under Windows. In fact,
%c (or "%c") should probably be the default, since CreateProcess()
runs batch files with the default shell, instead of some our value.
Also changed build_spawn_cmd() and build_run_cmd() to void, since
their return values are not used anywhere.
Modified Paths:
--------------
src/build.c
Modified: src/build.c
279 lines changed, 45 insertions(+), 234 deletions(-)
===================================================================
@@ -44,6 +44,7 @@
#include "prefs.h"
#include "projectprivate.h"
#include "sciwrappers.h"
+#include "spawn.h"
#include "support.h"
#include "toolbar.h"
#include "ui_utils.h"
@@ -60,20 +61,8 @@
#include <errno.h>
#include <glib/gstdio.h>
-#ifdef G_OS_UNIX
-# include <sys/types.h>
-# include <sys/wait.h>
-# include <signal.h>
-#else
-# include <windows.h>
-#endif
-/* g_spawn_async_with_pipes doesn't work on Windows */
-#ifdef G_OS_WIN32
-#define SYNC_SPAWN
-#endif
-
/* Number of editor indicators to draw - limited as this can affect performance */
#define GEANY_BUILD_ERR_HIGHLIGHT_MAX 50
@@ -124,12 +113,10 @@ widgets;
static guint build_groups_count[GEANY_GBG_COUNT] = { 3, 4, 2 };
static guint build_items_count = 9;
-#ifndef SYNC_SPAWN
-static void build_exit_cb(GPid child_pid, gint status, gpointer user_data);
-static gboolean build_iofunc(GIOChannel *ioc, GIOCondition cond, gpointer data);
-#endif
+static void build_exit_cb(GPid pid, gint status, gpointer user_data);
+static void build_iofunc(GString *string, GIOCondition condition, gpointer data);
static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error);
-static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir);
+static void build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir);
static void set_stop_button(gboolean stop);
static void run_exit_cb(GPid child_pid, gint status, gpointer user_data);
static void on_set_build_commands_activate(GtkWidget *w, gpointer u);
@@ -673,47 +660,6 @@ static void clear_all_errors(void)
}
-#ifdef SYNC_SPAWN
-static void parse_build_output(const gchar **output, gint status)
-{
- guint x, i, len;
- gchar *line, **lines;
-
- for (x = 0; x < 2; x++)
- {
- if (!EMPTY(output[x]))
- {
- lines = g_strsplit_set(output[x], "\r\n", -1);
- len = g_strv_length(lines);
-
- for (i = 0; i < len; i++)
- {
- if (!EMPTY(lines[i]))
- {
- line = lines[i];
- while (*line != '\0')
- { /* replace any control characters in the output */
- if (*line < 32)
- *line = 32;
- line++;
- }
- process_build_output_line(lines[i], COLOR_BLACK);
- }
- }
- g_strfreev(lines);
- }
- }
-
- show_build_result_message(status != 0);
- utils_beep();
-
- build_info.pid = 0;
- /* enable build items again */
- build_menu_update(NULL);
-}
-#endif
-
-
/* Replaces occurences of %e and %p with the appropriate filenames and
* %l with current line number. %d and %p replacements should be in UTF8 */
static gchar *build_replace_placeholder(const GeanyDocument *doc, const gchar *src)
@@ -782,43 +728,29 @@ static gchar *build_replace_placeholder(const GeanyDocument *doc, const gchar *s
/* dir is the UTF-8 working directory to run cmd in. It can be NULL to use the
* idx document directory */
-static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir)
+static void build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir)
{
GError *error = NULL;
- gchar **argv;
+#ifdef G_OS_UNIX
+ /* under Unix, start cmd via sh for compatibility */
+ gchar *argv[] = { "/bin/sh", "-c", (gchar *) cmd, NULL };
+#endif
gchar *working_dir;
gchar *utf8_working_dir;
gchar *utf8_cmd_string;
-#ifdef SYNC_SPAWN
- gchar *output[2];
- gint status;
-#else
- gint stdout_fd;
- gint stderr_fd;
-#endif
- g_return_val_if_fail(doc == NULL || doc->is_valid, (GPid) -1);
+ g_return_if_fail(doc == NULL || doc->is_valid);
- if (!((doc != NULL && !EMPTY(doc->file_name)) || !EMPTY(dir)))
+ if ((doc == NULL || EMPTY(doc->file_name)) && EMPTY(dir))
{
geany_debug("Failed to run command with no working directory");
ui_set_statusbar(TRUE, _("Process failed, no working directory"));
- return (GPid) 1;
+ return;
}
clear_all_errors();
SETPTR(current_dir_entered, NULL);
-#ifdef G_OS_WIN32
- argv = g_strsplit(cmd, " ", 0);
-#else
- argv = g_new0(gchar *, 4);
- argv[0] = g_strdup("/bin/sh");
- argv[1] = g_strdup("-c");
- argv[2] = g_strdup(cmd);
- argv[3] = NULL;
-#endif
-
utf8_cmd_string = utils_get_utf8_from_locale(cmd);
utf8_working_dir = !EMPTY(dir) ? g_strdup(dir) : g_path_get_dirname(doc->file_name);
working_dir = utils_get_locale_from_utf8(utf8_working_dir);
@@ -835,47 +767,22 @@ static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *d
build_info.file_type_id = (doc == NULL) ? GEANY_FILETYPES_NONE : doc->file_type->id;
build_info.message_count = 0;
-#ifdef SYNC_SPAWN
- if (! utils_spawn_sync(working_dir, argv, NULL, G_SPAWN_SEARCH_PATH,
- NULL, NULL, &output[0], &output[1], &status, &error))
+#ifdef G_OS_WIN32
+ if (!spawn_with_callbacks(working_dir, cmd, NULL, NULL, 0, NULL, NULL, build_iofunc,
#else
- if (! g_spawn_async_with_pipes(working_dir, argv, NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
- &(build_info.pid), NULL, &stdout_fd, &stderr_fd, &error))
+ /* cmd is passed via argv, so check it explicitly */
+ if (!spawn_check_command(cmd, FALSE, &error) ||
+ !spawn_with_callbacks(working_dir, NULL, argv, NULL, 0, NULL, NULL, build_iofunc,
#endif
+ GINT_TO_POINTER(0), 0, build_iofunc, GINT_TO_POINTER(1), 0, build_exit_cb,
+ NULL, &build_info.pid, &error))
{
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);
- g_free(working_dir);
- error = NULL;
- return (GPid) 0;
- }
-
-#ifdef SYNC_SPAWN
- parse_build_output((const gchar**) output, status);
- g_free(output[0]);
- g_free(output[1]);
-#else
- if (build_info.pid != 0)
- {
- g_child_watch_add(build_info.pid, (GChildWatchFunc) build_exit_cb, NULL);
- build_menu_update(doc);
- ui_progress_bar_start(NULL);
}
- /* use GIOChannels to monitor stdout and stderr */
- utils_set_up_io_channel(stdout_fd, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- TRUE, build_iofunc, GINT_TO_POINTER(0));
- utils_set_up_io_channel(stderr_fd, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- TRUE, build_iofunc, GINT_TO_POINTER(1));
-#endif
-
- g_strfreev(argv);
g_free(working_dir);
-
- return build_info.pid;
}
@@ -901,13 +808,10 @@ static gchar *prepare_run_cmd(GeanyDocument *doc, gchar **working_dir, guint cmd
working_dir_utf8 = build_replace_placeholder(doc, cmd_working_dir);
*working_dir = utils_get_locale_from_utf8(working_dir_utf8);
- /* only test whether working dir exists, don't change it or else Windows support will break
- * (gspawn-win32-helper.exe is used by GLib and must be in $PATH which means current working
- * dir where geany.exe was started from, so we can't change it) */
if (EMPTY(*working_dir) || ! g_file_test(*working_dir, G_FILE_TEST_EXISTS) ||
! g_file_test(*working_dir, G_FILE_TEST_IS_DIR))
{
- ui_set_statusbar(TRUE, _("Failed to change the working directory to \"%s\""),
+ ui_set_statusbar(TRUE, _("Invalid working directory \"%s\""),
!EMPTY(working_dir_utf8) ? working_dir_utf8 : "<NULL>" );
utils_free_pointers(3, cmd_string_utf8, working_dir_utf8, *working_dir, NULL);
return NULL;
@@ -943,18 +847,17 @@ static gchar *prepare_run_cmd(GeanyDocument *doc, gchar **working_dir, guint cmd
}
-static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
+static void build_run_cmd(GeanyDocument *doc, guint cmdindex)
{
gchar *working_dir;
gchar *run_cmd = NULL;
- GError *error = NULL;
if (! DOC_VALID(doc) || doc->file_name == NULL)
- return (GPid) 0;
+ return;
run_cmd = prepare_run_cmd(doc, &working_dir, cmdindex);
if (run_cmd == NULL)
- return (GPid) 0;
+ return;
run_info[cmdindex].file_type_id = doc->file_type->id;
@@ -988,79 +891,35 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
msgwin_show_hide(TRUE);
run_info[cmdindex].pid = 1;
-
g_free(vte_cmd);
}
else
#endif
{
- gchar *locale_term_cmd = NULL;
- gint argv_len, i;
- gchar **argv = NULL;
- gchar *script_path = NULL;
+ gchar *locale_term_cmd = utils_get_locale_from_utf8(tool_prefs.term_cmd);
+ GError *error = NULL;
- /* get the terminal path */
- locale_term_cmd = utils_get_locale_from_utf8(tool_prefs.term_cmd);
- /* split the term_cmd, so arguments will work too */
- if (!g_shell_parse_argv(locale_term_cmd, &argv_len, &argv, NULL))
- {
- ui_set_statusbar(TRUE,
- _("Could not parse terminal command \"%s\" "
- "(check Terminal tool setting in Preferences)"), tool_prefs.term_cmd);
- run_info[cmdindex].pid = (GPid) 1;
- g_unlink(run_cmd);
- goto free_strings;
- }
+ utils_str_replace_all(&locale_term_cmd, "%c", run_cmd);
- /* check that terminal exists (to prevent misleading error messages) */
- if (argv[0] != NULL)
+ if (spawn_async(working_dir, locale_term_cmd, NULL, NULL, &(run_info[cmdindex].pid),
+ &error))
{
- gchar *tmp = argv[0];
- /* g_find_program_in_path checks whether tmp exists and is executable */
- argv[0] = g_find_program_in_path(tmp);
- g_free(tmp);
- }
- if (argv[0] == NULL)
- {
- ui_set_statusbar(TRUE,
- _("Could not find terminal \"%s\" "
- "(check path for Terminal tool setting in Preferences)"), tool_prefs.term_cmd);
- run_info[cmdindex].pid = (GPid) 1;
- g_unlink(run_cmd);
- goto free_strings;
- }
-
- for (i = 0; i < argv_len; i++)
- {
- utils_str_replace_all(&(argv[i]), "%c", run_cmd);
+ g_child_watch_add(run_info[cmdindex].pid, (GChildWatchFunc) run_exit_cb,
+ (gpointer) &(run_info[cmdindex]));
+ build_menu_update(doc);
}
-
- if (! g_spawn_async(working_dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &(run_info[cmdindex].pid), &error))
+ else
{
- geany_debug("g_spawn_async() failed: %s", error->message);
+ geany_debug("spawn_async() failed: %s", error->message);
ui_set_statusbar(TRUE, _("Process failed (%s)"), error->message);
g_error_free(error);
g_unlink(run_cmd);
- error = NULL;
run_info[cmdindex].pid = (GPid) 0;
}
-
- if (run_info[cmdindex].pid != 0)
- {
- g_child_watch_add(run_info[cmdindex].pid, (GChildWatchFunc) run_exit_cb,
- (gpointer)&(run_info[cmdindex]));
- build_menu_update(doc);
- }
- free_strings:
- g_strfreev(argv);
- g_free(locale_term_cmd);
- g_free(script_path);
}
g_free(working_dir);
g_free(run_cmd);
- return run_info[cmdindex].pid;
}
@@ -1071,7 +930,6 @@ static void process_build_output_line(const gchar *str, gint color)
gint line;
msg = g_strdup(str);
-
g_strchomp(msg);
if (EMPTY(msg))
@@ -1108,29 +966,14 @@ static void process_build_output_line(const gchar *str, gint color)
}
-#ifndef SYNC_SPAWN
-static gboolean build_iofunc(GIOChannel *ioc, GIOCondition cond, gpointer data)
+static void build_iofunc(GString *string, GIOCondition condition, gpointer data)
{
- if (cond & (G_IO_IN | G_IO_PRI))
+ if (condition & (G_IO_IN | G_IO_PRI))
{
- gchar *msg;
- GIOStatus st;
-
- while ((st = g_io_channel_read_line(ioc, &msg, NULL, NULL, NULL)) == G_IO_STATUS_NORMAL && msg)
- {
- gint color = (GPOINTER_TO_INT(data)) ? COLOR_DARK_RED : COLOR_BLACK;
-
- process_build_output_line(msg, color);
- g_free(msg);
- }
- if (st == G_IO_STATUS_ERROR || st == G_IO_STATUS_EOF) return FALSE;
+ process_build_output_line(string->str,
+ (GPOINTER_TO_INT(data)) ? COLOR_DARK_RED : COLOR_BLACK);
}
- if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
- return FALSE;
-
- return TRUE;
}
-#endif
gboolean build_parse_make_dir(const gchar *string, gchar **prefix)
@@ -1203,40 +1046,16 @@ static void show_build_result_message(gboolean failure)
}
-#ifndef SYNC_SPAWN
static void build_exit_cb(GPid child_pid, gint status, gpointer user_data)
{
- gboolean failure = FALSE;
-
-#ifdef G_OS_WIN32
- failure = status;
-#else
- if (WIFEXITED(status))
- {
- if (WEXITSTATUS(status) != EXIT_SUCCESS)
- failure = TRUE;
- }
- else if (WIFSIGNALED(status))
- {
- /* the terminating signal: WTERMSIG (status)); */
- failure = TRUE;
- }
- else
- { /* any other failure occured */
- failure = TRUE;
- }
-#endif
- show_build_result_message(failure);
-
+ show_build_result_message(!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS);
utils_beep();
- g_spawn_close_pid(child_pid);
build_info.pid = 0;
/* enable build items again */
build_menu_update(NULL);
ui_progress_bar_stop();
}
-#endif
static void run_exit_cb(GPid child_pid, gint status, gpointer user_data)
@@ -1788,26 +1607,18 @@ static void on_toolbutton_make_activate(GtkWidget *menuitem, gpointer user_data)
static void kill_process(GPid *pid)
{
- gint result;
-
-#ifdef G_OS_WIN32
- g_return_if_fail(*pid != NULL);
- result = TerminateProcess(*pid, 0);
- /* TerminateProcess() returns TRUE on success, for the check below we have to convert
- * it to FALSE (and vice versa) */
- result = ! result;
-#else
- g_return_if_fail(*pid > 1);
- result = kill(*pid, SIGTERM);
-#endif
+ GError *error = NULL;
- if (result != 0)
- ui_set_statusbar(TRUE, _("Process could not be stopped (%s)."), g_strerror(errno));
- else
+ if (spawn_kill_process(*pid, &error))
{
*pid = 0;
build_menu_update(NULL);
}
+ else
+ {
+ ui_set_statusbar(TRUE, _("Process could not be stopped (%s)."), error->message);
+ g_error_free(error);
+ }
}
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list