Skip to content

Commit 84adb64

Browse files
j6tgitster
authored andcommitted
maybe_flush_or_die: move a too-loose Windows specific error
check to compat Commit b2f5e26 (Windows: Work around an oddity when a pipe with no reader is written to) introduced a check for EINVAL after fflush() to fight spurious "Invalid argument" errors on Windows when a pipe was broken. But this check may hide real errors on systems that do not have the this odd behavior. Introduce an fflush wrapper in compat/mingw.* so that the treatment is only applied on Windows. Signed-off-by: Johannes Sixt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent bafc478 commit 84adb64

File tree

3 files changed

+26
-6
lines changed

3 files changed

+26
-6
lines changed

compat/mingw.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,28 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
335335
return freopen(filename, otype, stream);
336336
}
337337

338+
#undef fflush
339+
int mingw_fflush(FILE *stream)
340+
{
341+
int ret = fflush(stream);
342+
343+
/*
344+
* write() is used behind the scenes of stdio output functions.
345+
* Since git code does not check for errors after each stdio write
346+
* operation, it can happen that write() is called by a later
347+
* stdio function even if an earlier write() call failed. In the
348+
* case of a pipe whose readable end was closed, only the first
349+
* call to write() reports EPIPE on Windows. Subsequent write()
350+
* calls report EINVAL. It is impossible to notice whether this
351+
* fflush invocation triggered such a case, therefore, we have to
352+
* catch all EINVAL errors whole-sale.
353+
*/
354+
if (ret && errno == EINVAL)
355+
errno = EPIPE;
356+
357+
return ret;
358+
}
359+
338360
/*
339361
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
340362
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.

compat/mingw.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ FILE *mingw_fopen (const char *filename, const char *otype);
185185
FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream);
186186
#define freopen mingw_freopen
187187

188+
int mingw_fflush(FILE *stream);
189+
#define fflush mingw_fflush
190+
188191
char *mingw_getcwd(char *pointer, int len);
189192
#define getcwd mingw_getcwd
190193

write_or_die.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,7 @@ void maybe_flush_or_die(FILE *f, const char *desc)
3434
return;
3535
}
3636
if (fflush(f)) {
37-
/*
38-
* On Windows, EPIPE is returned only by the first write()
39-
* after the reading end has closed its handle; subsequent
40-
* write()s return EINVAL.
41-
*/
42-
if (errno == EPIPE || errno == EINVAL)
37+
if (errno == EPIPE)
4338
exit(0);
4439
die_errno("write failure on '%s'", desc);
4540
}

0 commit comments

Comments
 (0)