Revision: 2290 http://geany.svn.sourceforge.net/geany/?rev=2290&view=rev Author: eht16 Date: 2008-02-27 08:08:07 -0800 (Wed, 27 Feb 2008)
Log Message: ----------- Apply patch from Pierre Joye to improve new Win32 process spawning code (thanks).
Modified Paths: -------------- trunk/ChangeLog trunk/src/utils.c trunk/src/win32.c trunk/src/win32.h
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2008-02-27 14:23:13 UTC (rev 2289) +++ trunk/ChangeLog 2008-02-27 16:08:07 UTC (rev 2290) @@ -6,6 +6,9 @@ active (introduced in r2253). * src/document.c, src/utils.c, src/utils.h: Fix a few more compiler warnings (type conversion warnings). + * src/utils.c, src/win32.c, src/win32.h: + Apply patch from Pierre Joye to improve new Win32 process spawning + code (thanks).
2008-02-26 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
Modified: trunk/src/utils.c =================================================================== --- trunk/src/utils.c 2008-02-27 14:23:13 UTC (rev 2289) +++ trunk/src/utils.c 2008-02-27 16:08:07 UTC (rev 2290) @@ -1849,10 +1849,7 @@ *std_err = NULL;
#ifdef G_OS_WIN32 - result = win32_spawn(dir, argv, env, flags, std_out, std_err, exit_status); - /** TODO create error messages in win32_spawn with appropriate error message text **/ - if (! result) - *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Process could not be created.")); + result = win32_spawn(dir, argv, env, flags, std_out, std_err, exit_status, error); #else result = g_spawn_sync(dir, argv, env, flags, NULL, NULL, std_out, std_err, exit_status, error); #endif @@ -1892,10 +1889,7 @@ }
#ifdef G_OS_WIN32 - result = win32_spawn(dir, argv, env, flags, NULL, NULL, NULL); - /** TODO create error messages in win32_spawn with appropriate error message text **/ - if (! result) - *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Process could not be created.")); + result = win32_spawn(dir, argv, env, flags, NULL, NULL, NULL, error); #else result = g_spawn_async(dir, argv, env, flags, NULL, NULL, child_pid, error); #endif
Modified: trunk/src/win32.c =================================================================== --- trunk/src/win32.c 2008-02-27 14:23:13 UTC (rev 2289) +++ trunk/src/win32.c 2008-02-27 16:08:07 UTC (rev 2290) @@ -67,16 +67,17 @@ HANDLE hInputFile; HANDLE hStdout; HANDLE hStderr; + HANDLE processId; + DWORD dwExitCode; }; typedef struct _geany_win32_spawn geany_win32_spawn;
+static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error); +static HANDLE GetTempFileHandle(GError **error); +static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, const TCHAR *dir, GError **error); +static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile, GError **error);
-static gboolean GetContentFromHandle(HANDLE hFile, gchar **content); -static HANDLE GetTempFileHandle(void); -static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, const TCHAR *dir); -static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile);
- static gchar *get_file_filters() { gchar *string; @@ -736,7 +737,7 @@ /* 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, - gchar **std_out, gchar **std_err, gint *exit_status) + gchar **std_out, gchar **std_err, gint *exit_status, GError **error) { TCHAR buffer[MAX_PATH]=TEXT(""); TCHAR cmdline[MAX_PATH] = TEXT(""); @@ -781,20 +782,26 @@
if (std_err != NULL) { - hStderrTempFile = GetTempFileHandle(); + hStderrTempFile = GetTempFileHandle(error); if (hStderrTempFile == INVALID_HANDLE_VALUE) { - geany_debug("win32_spawn: Second CreateFile failed (%d)\n", (gint) GetLastError()); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("win32_spawn: Second CreateFile failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR, msg); + g_free(msg); return FALSE; } }
if (std_out != NULL) { - hStdoutTempFile = GetTempFileHandle(); + hStdoutTempFile = GetTempFileHandle(error); if (hStdoutTempFile == INVALID_HANDLE_VALUE) { - geany_debug("win32_spawn: Second CreateFile failed (%d)\n", (gint) GetLastError()); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("win32_spawn: Second CreateFile failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR, msg); + g_free(msg); return FALSE; } } @@ -807,11 +814,15 @@ /* Get the handle to the current STDOUT and STDERR. */ gw_spawn.hStdout = GetStdHandle(STD_OUTPUT_HANDLE); gw_spawn.hStderr = GetStdHandle(STD_ERROR_HANDLE); + gw_spawn.dwExitCode = 0;
/* Create a pipe for the child process's STDOUT. */ if (! CreatePipe(&(gw_spawn.hChildStdoutRd), &(gw_spawn.hChildStdoutWr), &saAttr, 0)) { - geany_debug("win32_spawn: Stdout pipe creation failed\n"); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("win32_spawn: Stdout pipe creation failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_PIPE, msg); + g_free(msg); return FALSE; }
@@ -821,7 +832,10 @@ /* Create a pipe for the child process's STDERR. */ if (!CreatePipe(&(gw_spawn.hChildStderrRd), &(gw_spawn.hChildStderrWr), &saAttr, 0)) { - geany_debug("win32_spawn: Stdout pipe creation failed\n"); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("win32_spawn: Stderr pipe creation failed"); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_PIPE, msg); + g_free(msg); return FALSE; }
@@ -831,42 +845,55 @@ /* Create a pipe for the child process's STDIN. */ if (!CreatePipe(&(gw_spawn.hChildStdinRd), &(gw_spawn.hChildStdinWr), &saAttr, 0)) { - geany_debug("win32_spawn: Stdin pipe creation failed\n"); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("win32_spawn: Stdin pipe creation failed"); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_PIPE, g_win32_error_message (GetLastError())); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_PIPE, msg); + g_free(msg); return FALSE; }
/* Ensure that the write handle to the child process's pipe for STDIN is not inherited. */ SetHandleInformation(gw_spawn.hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
+ /* Now create the child process. */ + fSuccess = CreateChildProcess(&gw_spawn, cmdline, dir, error); + if (exit_status) + { + *exit_status = gw_spawn.dwExitCode; + }
- /* Now create the child process. */ - fSuccess = CreateChildProcess(&gw_spawn, cmdline, dir); if (!fSuccess) { - geany_debug("win32_spawn: Create process failed with"); + geany_debug("win32_spawn: Create process failed"); return FALSE; }
/* Read from pipe that is the standard output for child process. */ if (std_out != NULL) { - ReadFromPipe(gw_spawn.hChildStdoutRd, gw_spawn.hChildStdoutWr, hStdoutTempFile); - GetContentFromHandle(hStdoutTempFile, &stdout_content); + ReadFromPipe(gw_spawn.hChildStdoutRd, gw_spawn.hChildStdoutWr, hStdoutTempFile, error); + if (!GetContentFromHandle(hStdoutTempFile, &stdout_content, error)) + { + return FALSE; + } *std_out = stdout_content; }
if (std_err != NULL) { - ReadFromPipe(gw_spawn.hChildStderrRd, gw_spawn.hChildStderrWr, hStderrTempFile); - GetContentFromHandle(hStderrTempFile, &stderr_content); + ReadFromPipe(gw_spawn.hChildStderrRd, gw_spawn.hChildStderrWr, hStderrTempFile, error); + if (!GetContentFromHandle(hStderrTempFile, &stderr_content, error)) + { + return FALSE; + } *std_err = stderr_content; } - return TRUE; }
-static gboolean GetContentFromHandle(HANDLE hFile, gchar **content) +static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error) { DWORD filesize; gchar * buffer; @@ -882,7 +909,10 @@ buffer = g_malloc(sizeof(gchar*) * (filesize+1)); if (!buffer) { + gchar *msg = g_win32_error_message(GetLastError()); geany_debug("GetContentFromHandle: Alloc failed"); + *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR, msg); + g_free(msg); return FALSE; }
@@ -890,13 +920,19 @@ if (!ReadFile(hFile, buffer, filesize, &dwRead, NULL) || dwRead == 0) { + gchar *msg = g_win32_error_message(GetLastError()); geany_debug("GetContentFromHandle: Cannot read tempfile"); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_FAILED, msg); + g_free(msg); return FALSE; }
if (!CloseHandle (hFile)) { - geany_debug("GetContentFromHandle: CloseHandle failed (%d)\n", (gint) GetLastError()); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("GetContentFromHandle: CloseHandle failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_FAILED, msg); + g_free(msg); g_free(buffer); *content = NULL; return FALSE; @@ -906,7 +942,7 @@ }
-static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, const TCHAR *dir) +static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, const TCHAR *dir, GError **error) { PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; @@ -938,11 +974,30 @@
if (bFuncRetn == 0) { - geany_debug("CreateChildProcess: CreateProcess failed\n"); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("CreateChildProcess: CreateProcess failed"); + *error = g_error_new(G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, msg); + g_free(msg); return FALSE; } else { + int i; + DWORD dwStatus; + + for (i = 0; i < 2 && (dwStatus = WaitForSingleObject(piProcInfo.hProcess, 30*1000)) == WAIT_TIMEOUT; i++) + { + geany_debug("CreateChildProcess: CreateProcess failed"); + TerminateProcess(piProcInfo.hProcess, WAIT_TIMEOUT); /* NOTE: This will not kill grandkids. */ + } + + if (GetExitCodeProcess(piProcInfo.hProcess, &gw_spawn->dwExitCode) != 0) + { + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("GetExitCodeProcess failed"); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_FAILED, msg); + g_free(msg); + } CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); return bFuncRetn; @@ -951,7 +1006,7 @@ }
-static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile) +static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile, GError **error) { DWORD dwRead, dwWritten; CHAR chBuf[BUFSIZE]; @@ -960,7 +1015,10 @@ read end of the pipe. */ if (!CloseHandle(hWrite)) { + gchar *msg = g_win32_error_message(GetLastError()); geany_debug("ReadFromPipe: Closing handle failed"); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR_PIPE, msg); + g_free(msg); return; }
@@ -976,7 +1034,7 @@ }
-static HANDLE GetTempFileHandle(void) +static HANDLE GetTempFileHandle(GError **error) { /* Temp file */ DWORD dwBufSize=BUFSIZE; @@ -992,7 +1050,10 @@
if (dwRetVal > dwBufSize || (dwRetVal == 0)) { - geany_debug("GetTempFileHandle: GetTempPath failed (%d)\n", (gint) GetLastError()); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("GetTempFileHandle: GetTempPath failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR, msg); + g_free(msg); return NULL; }
@@ -1003,7 +1064,10 @@ szTempName); /* buffer for name */ if (uRetVal == 0) { - geany_debug("GetTempFileName failed (%d)\n", (gint) GetLastError()); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("GetTempFileName failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR, msg); + g_free(msg); return NULL; }
@@ -1017,7 +1081,10 @@
if (hTempFile == INVALID_HANDLE_VALUE) { - geany_debug("GetTempFileHandle: Second CreateFile failed (%d)\n", (gint) GetLastError()); + gchar *msg = g_win32_error_message(GetLastError()); + geany_debug("GetTempFileHandle: Second CreateFile failed (%d)", (gint) GetLastError()); + *error = g_error_new(G_SPAWN_ERROR, G_FILE_ERROR, msg); + g_free(msg); return NULL; } return hTempFile;
Modified: trunk/src/win32.h =================================================================== --- trunk/src/win32.h 2008-02-27 14:23:13 UTC (rev 2289) +++ trunk/src/win32.h 2008-02-27 16:08:07 UTC (rev 2290) @@ -33,23 +33,16 @@
void win32_show_color_dialog(const gchar *colour);
-/* Creates a native Windows message box of the given type and returns always TRUE - * or FALSE representing th pressed Yes or No button. - * If type is not GTK_MESSAGE_QUESTION, it returns always TRUE. */ gboolean win32_message_dialog(GtkWidget *parent, GtkMessageType type, const gchar *msg);
-/* Special dialog to ask for an action when closing an unsaved file */ gint win32_message_dialog_unsaved(const gchar *msg);
-/* Just a simple wrapper function to open a browser window */ void win32_open_browser(const gchar *uri);
gchar *win32_show_project_open_dialog(GtkWidget *parent, const gchar *title, const gchar *initial_dir, gboolean allow_new_file, gboolean project_file_filter);
-/* Shows a folder selection dialog. - * The selected folder name is returned. */ gchar *win32_show_project_folder_dialog(GtkWidget *parent, const gchar *title, const gchar *initial_dir);
@@ -62,6 +55,6 @@ gchar *win32_get_hostname();
gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags, - gchar **std_out, gchar **std_err, gint *exit_status); + gchar **std_out, gchar **std_err, gint *exit_status, GError **error);
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.