git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 1/3] mingw: add experimental feature to redirect standard handles

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Nov 1, 2017, 17:10 UTC
Message-ID
<21f71a95fbb1626ad5b98065571175c06e858f92.1509556153.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1509556153.git.johannes.schindelin@gmx.de>

Particularly when calling Git from applications, such as Visual Studio's Team Explorer, it is important that stdin/stdout/stderr are closed properly. However, when spawning processes on Windows, those handles must be marked as inheritable if we want to use them, but that flag is a global flag and may very well be used by other spawned processes which then do not know to close those handles.

Let's introduce a set of environment variables (GIT_REDIRECT_STDIN and friends) that specify paths to files, or even better, named pipes (which are similar to Unix sockets) and that are used by the spawned Git process. This helps work around above-mentioned issue: those named pipes will be opened in a non-inheritable way upon startup, and no handles are passed around (and therefore no inherited handles need to be closed by any spawned child).

This feature shipped with Git for Windows (marked as experimental) since v2.11.0(2), so it has seen some serious testing in the meantime.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 compat/mingw.c  | 43 +++++++++++++++++++++++++++++++++++++++++++
 t/t0001-init.sh |  6 ++++++
 2 files changed, 49 insertions(+)
diff --git a/compat/mingw.c b/compat/mingw.c
index 8b6fa0db446..6c6c7795a70 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2139,6 +2139,47 @@ static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
 	return memcpy(malloc_startup(len), buffer, len);
 }
 
+static void maybe_redirect_std_handle(const wchar_t *key, DWORD std_id, int fd,
+				      DWORD desired_access, DWORD flags)
+{
+	DWORD create_flag = fd ? OPEN_ALWAYS : OPEN_EXISTING;
+	wchar_t buf[MAX_PATH];
+	DWORD max = ARRAY_SIZE(buf);
+	HANDLE handle;
+	DWORD ret = GetEnvironmentVariableW(key, buf, max);
+
+	if (!ret || ret >= max)
+		return;
+
+	/* make sure this does not leak into child processes */
+	SetEnvironmentVariableW(key, NULL);
+	if (!wcscmp(buf, L"off")) {
+		close(fd);
+		handle = GetStdHandle(std_id);
+		if (handle != INVALID_HANDLE_VALUE)
+			CloseHandle(handle);
+		return;
+	}
+	handle = CreateFileW(buf, desired_access, 0, NULL, create_flag,
+			     flags, NULL);
+	if (handle != INVALID_HANDLE_VALUE) {
+		int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
+		SetStdHandle(std_id, handle);
+		dup2(new_fd, fd);
+		close(new_fd);
+	}
+}
+
+static void maybe_redirect_std_handles(void)
+{
+	maybe_redirect_std_handle(L"GIT_REDIRECT_STDIN", STD_INPUT_HANDLE, 0,
+				  GENERIC_READ, FILE_ATTRIBUTE_NORMAL);
+	maybe_redirect_std_handle(L"GIT_REDIRECT_STDOUT", STD_OUTPUT_HANDLE, 1,
+				  GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL);
+	maybe_redirect_std_handle(L"GIT_REDIRECT_STDERR", STD_ERROR_HANDLE, 2,
+				  GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
+}
+
 void mingw_startup(void)
 {
 	int i, maxlen, argc;
@@ -2146,6 +2187,8 @@ void mingw_startup(void)
 	wchar_t **wenv, **wargv;
 	_startupinfo si;
 
+	maybe_redirect_std_handles();
+
 	/* get wide char arguments and environment */
 	si.newmode = 0;
 	if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 86c1a51654f..0fd2fc45385 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -453,4 +453,10 @@ test_expect_success 're-init from a linked worktree' '
 	)
 '
 
+test_expect_success MINGW 'redirect std handles' '
+	GIT_REDIRECT_STDOUT=output.txt git rev-parse --git-dir &&
+	test .git = "$(cat output.txt)" &&
+	test -z "$(GIT_REDIRECT_STDOUT=off git rev-parse --git-dir)"
+'
+
 test_done
-- 
2.15.0.windows.1
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 20 of 22 in “mingw: introduce a way to avoid std handle inheritance”
  1. 0/3 mingw: introduce a way to avoid std handle inheritanceJohannes Schindelin, Oct 30, 2017
  2. 1/3 mingw: add experimental feature to redirect standard handlesJohannes Schindelin, Oct 30, 2017
  3. 2/3 mingw: special-case GIT_REDIRECT_STDERR=2>&1Johannes Schindelin, Oct 30, 2017
  4. 3/3 mingw: document the experimental standard handle redirectionJohannes Schindelin, Oct 30, 2017
  5. Eric SunshineOct 30, 2017
  6. Johannes SchindelinOct 31, 2017
  7. Junio C HamanoNov 1, 2017
  8. Johannes SchindelinNov 1, 2017
  9. Junio C HamanoNov 2, 2017
  10. Johannes SchindelinNov 2, 2017
  11. Junio C HamanoNov 3, 2017
  12. Johannes SchindelinNov 3, 2017
  13. Jonathan NiederOct 30, 2017
  14. Junio C HamanoOct 31, 2017
  15. Johannes SchindelinOct 31, 2017
  16. Jonathan NiederOct 31, 2017
  17. Johannes SchindelinNov 1, 2017
  18. Stefan BellerNov 1, 2017
  19. 0/3 mingw: introduce a way to avoid std handle inheritanceJohannes Schindelin, Nov 1, 2017
  20. 1/3 mingw: add experimental feature to redirect standard handlesJohannes Schindelin, Nov 1, 2017
  21. 2/3 mingw: optionally redirect stderr/stdout via the same handleJohannes Schindelin, Nov 1, 2017
  22. 3/3 mingw: document the standard handle redirectionJohannes Schindelin, Nov 1, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.