Skip to content

Commit 69d9904

Browse files
committed
git wrapper: allow _Git Bash_ to run with a newly allocated console
With a recent change in Cygwin (which is the basis of the msys2-runtime), a GUI process desiring to launch an MSys2 executable needs to allocate a console for the new process (otherwise the process will just hang on Windows XP). _Git Bash_ is such a GUI process. While at it, use correct handles when inheriting the stdin/stdout/stderr handles: `GetStdHandle()` returns NULL for invalid handles, but the STARTUPINFO must specify `INVALID_HANDLE_VALUE` instead. Originally, the hope was that only this `NULL` => `INVALID_HANDLE_VALUE` conversion would be required to fix the Windows XP issue mentioned above (extensive debugging revealed that starting _Git Bash_ on Windows XP would yield invalid handles for `stdin` and `stderr`, but *not* for `stdout`). However, while _Git Bash_ eventually showed a `mintty` when not allocating a new console, it took around one second to show it, and several seconds to close it. So let's just include both fixes. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 8bba470 commit 69d9904

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

compat/win32/git-wrapper.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,9 @@ static int strip_prefix(LPWSTR str, int *len, LPCWSTR prefix)
187187
static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
188188
LPWSTR *prefix_args, int *prefix_args_len,
189189
int *is_git_command, LPWSTR *working_directory, int *full_path,
190-
int *skip_arguments)
190+
int *skip_arguments, int *allocate_console)
191191
{
192-
int id, minimal_search_path, wargc;
192+
int id, minimal_search_path, needs_a_console, wargc;
193193
LPWSTR *wargv;
194194

195195
#define BUFSIZE 65536
@@ -198,6 +198,7 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
198198

199199
for (id = 0; ; id++) {
200200
minimal_search_path = 0;
201+
needs_a_console = 0;
201202
len = LoadString(NULL, id, buf, BUFSIZE);
202203

203204
if (!len) {
@@ -218,6 +219,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
218219
for (;;) {
219220
if (strip_prefix(buf, &len, L"MINIMAL_PATH=1 "))
220221
minimal_search_path = 1;
222+
else if (strip_prefix(buf, &len, L"ALLOC_CONSOLE=1 "))
223+
needs_a_console = 1;
221224
else
222225
break;
223226
}
@@ -298,6 +301,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
298301
}
299302
if (minimal_search_path)
300303
*full_path = 0;
304+
if (needs_a_console)
305+
*allocate_console = 1;
301306
LocalFree(wargv);
302307

303308
return 1;
@@ -306,7 +311,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
306311
int main(void)
307312
{
308313
int r = 1, wait = 1, prefix_args_len = -1, needs_env_setup = 1,
309-
is_git_command = 1, full_path = 1, skip_arguments = 0;
314+
is_git_command = 1, full_path = 1, skip_arguments = 0,
315+
allocate_console = 0;
310316
WCHAR exepath[MAX_PATH], exe[MAX_PATH];
311317
LPWSTR cmd = NULL, exep = exe, prefix_args = NULL, basename;
312318
LPWSTR working_directory = NULL;
@@ -326,11 +332,12 @@ int main(void)
326332
if (configure_via_resource(basename, exepath, exep,
327333
&prefix_args, &prefix_args_len,
328334
&is_git_command, &working_directory,
329-
&full_path, &skip_arguments)) {
335+
&full_path, &skip_arguments, &allocate_console)) {
330336
/* do nothing */
331337
}
332338
else if (!wcsicmp(basename, L"git-gui.exe")) {
333339
static WCHAR buffer[BUFSIZE];
340+
allocate_console = 1;
334341
if (!PathRemoveFileSpec(exepath)) {
335342
fwprintf(stderr,
336343
L"Invalid executable path: %s\n", exepath);
@@ -386,6 +393,7 @@ int main(void)
386393
}
387394
else if (!wcsicmp(basename, L"gitk.exe")) {
388395
static WCHAR buffer[BUFSIZE];
396+
allocate_console = 1;
389397
if (!PathRemoveFileSpec(exepath)) {
390398
fwprintf(stderr,
391399
L"Invalid executable path: %s\n", exepath);
@@ -437,16 +445,20 @@ int main(void)
437445
ZeroMemory(&si, sizeof(STARTUPINFO));
438446
si.cb = sizeof(STARTUPINFO);
439447

440-
console_handle = CreateFile(L"CONOUT$", GENERIC_WRITE,
448+
if (allocate_console)
449+
creation_flags |= CREATE_NEW_CONSOLE;
450+
else if ((console_handle = CreateFile(L"CONOUT$", GENERIC_WRITE,
441451
FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
442-
FILE_ATTRIBUTE_NORMAL, NULL);
443-
if (console_handle != INVALID_HANDLE_VALUE)
452+
FILE_ATTRIBUTE_NORMAL, NULL)) !=
453+
INVALID_HANDLE_VALUE)
444454
CloseHandle(console_handle);
445455
else {
456+
#define STD_HANDLE(field, id) si.hStd##field = GetStdHandle(STD_##id); if (!si.hStd##field) si.hStd##field = INVALID_HANDLE_VALUE
457+
STD_HANDLE(Input, INPUT_HANDLE);
458+
STD_HANDLE(Output, OUTPUT_HANDLE);
459+
STD_HANDLE(Error, ERROR_HANDLE);
446460
si.dwFlags = STARTF_USESTDHANDLES;
447-
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
448-
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
449-
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
461+
450462

451463
creation_flags |= CREATE_NO_WINDOW;
452464
}
@@ -455,7 +467,8 @@ int main(void)
455467
cmd, /* modified command line */
456468
NULL, /* process handle inheritance */
457469
NULL, /* thread handle inheritance */
458-
TRUE, /* handles inheritable? */
470+
/* handles inheritable? */
471+
allocate_console ? FALSE : TRUE,
459472
creation_flags,
460473
NULL, /* environment: use parent */
461474
working_directory, /* use parent's */

0 commit comments

Comments
 (0)