git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <johannes.schindelin@gmx.de>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>
Subject: [PATCH 1/3] mingw: add experimental feature to redirect standard handles
Date: Mon, 30 Oct 2017 18:10:23 +0100 (CET)	[thread overview]
Message-ID: <804f26293de8f7cf805711313e376a513011a048.1509382976.git.johannes.schindelin@gmx.de> (raw)
In-Reply-To: <cover.1509382976.git.johannes.schindelin@gmx.de>

On Windows, file handles need to be marked inheritable when they need to
be used as standard input/output/error handles for a newly spawned
process. The problem with that, of course, is that the "inheritable" flag
is global and therefore can wreak havoc with highly multi-threaded
applications: other spawned processes will *also* inherit those file
handles, despite having *other* input/output/error handles, and never
close the former handles because they do not know about them.

Let's introduce a set of environment variables (GIT_REDIRECT_STDIN and
friends) that point to files, or even better, named pipes 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.

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



  reply	other threads:[~2017-10-30 17:10 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-30 17:10 [PATCH 0/3] mingw: introduce a way to avoid std handle inheritance Johannes Schindelin
2017-10-30 17:10 ` Johannes Schindelin [this message]
2017-10-30 17:10 ` [PATCH 2/3] mingw: special-case GIT_REDIRECT_STDERR=2>&1 Johannes Schindelin
2017-10-30 17:10 ` [PATCH 3/3] mingw: document the experimental standard handle redirection Johannes Schindelin
2017-10-30 18:58   ` Eric Sunshine
2017-10-31 17:08     ` Johannes Schindelin
2017-11-01  4:58       ` Junio C Hamano
2017-11-01 16:37         ` Johannes Schindelin
2017-11-02  1:31           ` Junio C Hamano
2017-11-02 17:20             ` Johannes Schindelin
2017-11-03  1:50               ` Junio C Hamano
2017-11-03 11:51                 ` Johannes Schindelin
2017-10-30 20:55 ` [PATCH 0/3] mingw: introduce a way to avoid std handle inheritance Jonathan Nieder
2017-10-31  5:48   ` Junio C Hamano
2017-10-31 17:12   ` Johannes Schindelin
2017-10-31 18:09     ` Jonathan Nieder
2017-11-01 17:07       ` Johannes Schindelin
2017-11-01 17:17         ` Stefan Beller
2017-11-01 17:10 ` [PATCH v2 " Johannes Schindelin
2017-11-01 17:10   ` [PATCH v2 1/3] mingw: add experimental feature to redirect standard handles Johannes Schindelin
2017-11-01 17:10   ` [PATCH v2 2/3] mingw: optionally redirect stderr/stdout via the same handle Johannes Schindelin
2017-11-01 17:10   ` [PATCH v2 3/3] mingw: document the standard handle redirection Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=804f26293de8f7cf805711313e376a513011a048.1509382976.git.johannes.schindelin@gmx.de \
    --to=johannes.schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).