Skip to content

Commit

Permalink
mingw: intercept isatty() to handle /dev/null as Git expects it
Browse files Browse the repository at this point in the history
When Git's source code calls isatty(), it really asks whether the
respective file descriptor is connected to an interactive terminal.

Windows' _isatty() function, however, determines whether the file
descriptor is associated with a character device. And NUL, Windows'
equivalent of /dev/null, is a character device.

Which means that for years, Git mistakenly detected an associated
interactive terminal when being run through the test suite, which
almost always redirects stdin, stdout and stderr to /dev/null.

This bug only became obvious, and painfully so, when the new
bisect--helper entered the `pu` branch and made the automatic build & test
time out because t6030 was waiting for an answer.

For details, see

	https://msdn.microsoft.com/en-us/library/f4s0ddew.aspx

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
dscho authored and gitster committed Dec 12, 2016
1 parent c3808ca commit cbb3f3c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
3 changes: 3 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ int mingw_raise(int sig);
* ANSI emulation wrappers
*/

int winansi_isatty(int fd);
#define isatty winansi_isatty

void winansi_init(void);
HANDLE winansi_get_osfhandle(int fd);

Expand Down
33 changes: 33 additions & 0 deletions compat/winansi.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <wingdi.h>
#include <winreg.h>

/* In this file, we actually want to use Windows' own isatty(). */
#undef isatty

/*
ANSI codes used by git: m, K
Expand Down Expand Up @@ -570,6 +573,36 @@ static void detect_msys_tty(int fd)

#endif

int winansi_isatty(int fd)
{
int res = isatty(fd);

if (res) {
/*
* Make sure that /dev/null is not fooling Git into believing
* that we are connected to a terminal, as "_isatty() returns a
* nonzero value if the descriptor is associated with a
* character device."; for more information, see
*
* https://msdn.microsoft.com/en-us/library/f4s0ddew.aspx
*/
HANDLE handle = (HANDLE)_get_osfhandle(fd);
if (fd == STDIN_FILENO) {
DWORD dummy;

if (!GetConsoleMode(handle, &dummy))
res = 0;
} else if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
CONSOLE_SCREEN_BUFFER_INFO dummy;

if (!GetConsoleScreenBufferInfo(handle, &dummy))
res = 0;
}
}

return res;
}

void winansi_init(void)
{
int con1, con2;
Expand Down

0 comments on commit cbb3f3c

Please sign in to comment.