Skip to content

Commit dc364ab

Browse files
committed
fixup! mingw: spawned processes need to inherit only standard handles
On Windows 7 and older, the API to restrict which file handles get to be inherited by a spawned process is a bit peculiar. For example, when launching `git ls-remote https://...` in a Git Bash, everything works as expected. But when launching that in a Git CMD, CreateProcessW() will fail (with an ERROR_NO_SYSTEM_RESOURCES) if even one of the standard handles are marked to be inherited specifically. Apparently, it has something to do with handles' file types and with cmd.exe setting up its standard handles in a specific way. Rather than trying to guess correctly under which circumstances we should, or should not, list those standard handles, let's just work around this by detecting that particular error and simply trying to call CreateProcessW() again, this time without any special thread attribute list to restrict which handles get to be inherited by the spawned process. This means that we potentially run into more locking problems on Windows 7 and older than we would like, but it is still better than to deny Git to spawn any child processes. This fixes git-for-windows#1475 Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 60d8d6e commit dc364ab

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

compat/mingw.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
15931593
const char *dir, const char *prepend_cmd,
15941594
int fhin, int fhout, int fherr)
15951595
{
1596-
static int atexit_handler_initialized;
1596+
static int atexit_handler_initialized, restrict_handle_inheritance = 1;
15971597
STARTUPINFOEXW si;
15981598
PROCESS_INFORMATION pi;
15991599
LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
@@ -1722,7 +1722,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
17221722
wenvblk = make_environment_block(deltaenv);
17231723

17241724
memset(&pi, 0, sizeof(pi));
1725-
if (stdhandles_count &&
1725+
if (restrict_handle_inheritance && stdhandles_count &&
17261726
(InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
17271727
GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
17281728
(attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
@@ -1741,6 +1741,25 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
17411741
stdhandles_count ? TRUE : FALSE,
17421742
flags, wenvblk, dir ? wdir : NULL,
17431743
&si.StartupInfo, &pi);
1744+
1745+
/*
1746+
* On Windows 2008 R2, it seems that specifying certain types of handles
1747+
* (such as FILE_TYPE_CHAR or FILE_TYPE_PIPE) will always produce an
1748+
* error. Rather than playing finicky and fragile games, let's just try
1749+
* to detect this situation and simply try again without restricting any
1750+
* handle inheritance. This is still better than failing to create
1751+
* processes.
1752+
*/
1753+
if (!ret && GetLastError() == ERROR_NO_SYSTEM_RESOURCES &&
1754+
restrict_handle_inheritance && stdhandles_count) {
1755+
restrict_handle_inheritance = 0;
1756+
flags &= ~EXTENDED_STARTUPINFO_PRESENT;
1757+
ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1758+
stdhandles_count ? TRUE : FALSE,
1759+
flags, wenvblk, dir ? wdir : NULL,
1760+
&si.StartupInfo, &pi);
1761+
}
1762+
17441763
if (!ret)
17451764
errno = err_win_to_posix(GetLastError());
17461765

0 commit comments

Comments
 (0)