Skip to content

Commit 06c6126

Browse files
gitsterGit for Windows Build Agent
authored andcommitted
Merge branch 'ps/object-collision-check'
CI jobs gave sporadic failures, which turns out that that the object finalization code was giving an error when it did not have to. * ps/object-collision-check: object-file: retry linking file into place when occluding file vanishes object-file: don't special-case missing source file in collision check object-file: rename variables in `check_collision()` object-file: fix race in object collision check Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 5cc6f5a + 703b948 commit 06c6126

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

object-file.c

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,54 +1970,59 @@ static void write_object_file_prepare_literally(const struct git_hash_algo *algo
19701970
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
19711971
}
19721972

1973-
static int check_collision(const char *filename_a, const char *filename_b)
1973+
#define CHECK_COLLISION_DEST_VANISHED -2
1974+
1975+
static int check_collision(const char *source, const char *dest)
19741976
{
1975-
char buf_a[4096], buf_b[4096];
1976-
int fd_a = -1, fd_b = -1;
1977+
char buf_source[4096], buf_dest[4096];
1978+
int fd_source = -1, fd_dest = -1;
19771979
int ret = 0;
19781980

1979-
fd_a = open(filename_a, O_RDONLY);
1980-
if (fd_a < 0) {
1981-
ret = error_errno(_("unable to open %s"), filename_a);
1981+
fd_source = open(source, O_RDONLY);
1982+
if (fd_source < 0) {
1983+
ret = error_errno(_("unable to open %s"), source);
19821984
goto out;
19831985
}
19841986

1985-
fd_b = open(filename_b, O_RDONLY);
1986-
if (fd_b < 0) {
1987-
ret = error_errno(_("unable to open %s"), filename_b);
1987+
fd_dest = open(dest, O_RDONLY);
1988+
if (fd_dest < 0) {
1989+
if (errno != ENOENT)
1990+
ret = error_errno(_("unable to open %s"), dest);
1991+
else
1992+
ret = CHECK_COLLISION_DEST_VANISHED;
19881993
goto out;
19891994
}
19901995

19911996
while (1) {
19921997
ssize_t sz_a, sz_b;
19931998

1994-
sz_a = read_in_full(fd_a, buf_a, sizeof(buf_a));
1999+
sz_a = read_in_full(fd_source, buf_source, sizeof(buf_source));
19952000
if (sz_a < 0) {
1996-
ret = error_errno(_("unable to read %s"), filename_a);
2001+
ret = error_errno(_("unable to read %s"), source);
19972002
goto out;
19982003
}
19992004

2000-
sz_b = read_in_full(fd_b, buf_b, sizeof(buf_b));
2005+
sz_b = read_in_full(fd_dest, buf_dest, sizeof(buf_dest));
20012006
if (sz_b < 0) {
2002-
ret = error_errno(_("unable to read %s"), filename_b);
2007+
ret = error_errno(_("unable to read %s"), dest);
20032008
goto out;
20042009
}
20052010

2006-
if (sz_a != sz_b || memcmp(buf_a, buf_b, sz_a)) {
2011+
if (sz_a != sz_b || memcmp(buf_source, buf_dest, sz_a)) {
20072012
ret = error(_("files '%s' and '%s' differ in contents"),
2008-
filename_a, filename_b);
2013+
source, dest);
20092014
goto out;
20102015
}
20112016

2012-
if (sz_a < sizeof(buf_a))
2017+
if (sz_a < sizeof(buf_source))
20132018
break;
20142019
}
20152020

20162021
out:
2017-
if (fd_a > -1)
2018-
close(fd_a);
2019-
if (fd_b > -1)
2020-
close(fd_b);
2022+
if (fd_source > -1)
2023+
close(fd_source);
2024+
if (fd_dest > -1)
2025+
close(fd_dest);
20212026
return ret;
20222027
}
20232028

@@ -2032,8 +2037,11 @@ int finalize_object_file(const char *tmpfile, const char *filename)
20322037
int finalize_object_file_flags(const char *tmpfile, const char *filename,
20332038
enum finalize_object_file_flags flags)
20342039
{
2035-
struct stat st;
2036-
int ret = 0;
2040+
unsigned retries = 0;
2041+
int ret;
2042+
2043+
retry:
2044+
ret = 0;
20372045

20382046
if (object_creation_mode == OBJECT_CREATION_USES_RENAMES)
20392047
goto try_rename;
@@ -2054,6 +2062,8 @@ int finalize_object_file_flags(const char *tmpfile, const char *filename,
20542062
* left to unlink.
20552063
*/
20562064
if (ret && ret != EEXIST) {
2065+
struct stat st;
2066+
20572067
try_rename:
20582068
if (!stat(filename, &st))
20592069
ret = EEXIST;
@@ -2069,9 +2079,17 @@ int finalize_object_file_flags(const char *tmpfile, const char *filename,
20692079
errno = saved_errno;
20702080
return error_errno(_("unable to write file %s"), filename);
20712081
}
2072-
if (!(flags & FOF_SKIP_COLLISION_CHECK) &&
2073-
check_collision(tmpfile, filename))
2082+
if (!(flags & FOF_SKIP_COLLISION_CHECK)) {
2083+
ret = check_collision(tmpfile, filename);
2084+
if (ret == CHECK_COLLISION_DEST_VANISHED) {
2085+
if (retries++ > 5)
2086+
return error(_("unable to write repeatedly vanishing file %s"),
2087+
filename);
2088+
goto retry;
2089+
}
2090+
else if (ret)
20742091
return -1;
2092+
}
20752093
unlink_or_warn(tmpfile);
20762094
}
20772095

0 commit comments

Comments
 (0)