diff options
author | Jeff King <peff@peff.net> | 2017-02-17 16:07:49 -0500 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-02-17 14:40:29 -0800 |
commit | 7e8c9355b7aa61948275c8144dff6857f4b0ee51 (patch) | |
tree | 11fff8a46820416edfa1f2da44f448546e8c9e85 /tempfile.c | |
parent | 0838cbc22fc9567ede7a60e800d876e733820060 (diff) | |
download | git-7e8c9355b7aa61948275c8144dff6857f4b0ee51.tar.gz |
tempfile: set errno to a known value before calling ferror()jk/tempfile-ferror-fclose-confusion
In close_tempfile(), we return an error if ferror()
indicated a previous failure, or if fclose() failed. In the
latter case, errno is set and it is useful for callers to
report it.
However, if _only_ ferror() triggers, then the value of
errno is based on whatever syscall happened to last fail,
which may not be related to our filehandle at all. A caller
cannot tell the difference between the two cases, and may
use "die_errno()" or similar to report a nonsense errno value.
One solution would be to actually pass back separate return
values for the two cases, so a caller can write a more
appropriate message for each case. But that makes the
interface clunky.
Instead, let's just set errno to the generic EIO in this case.
That's not as descriptive as we'd like, but at least it's
predictable. So it's better than the status quo in all cases
but one: when the last syscall really did involve a failure
on our filehandle, we'll be wiping that out. But that's a
fragile thing for us to rely on.
In any case, we'll let the errno result from fclose() take
precedence over our value, as we know that's recent and
accurate (and many I/O errors will persist through the
fclose anyway).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'tempfile.c')
-rw-r--r-- | tempfile.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/tempfile.c b/tempfile.c index ffcc272375..6843710670 100644 --- a/tempfile.c +++ b/tempfile.c @@ -247,8 +247,13 @@ int close_tempfile(struct tempfile *tempfile) tempfile->fd = -1; if (fp) { tempfile->fp = NULL; - err = ferror(fp); - err |= fclose(fp); + if (ferror(fp)) { + err = -1; + if (!fclose(fp)) + errno = EIO; + } else { + err = fclose(fp); + } } else { err = close(fd); } |