|
|
3de368 |
From 5bc590cd3ce202243cd1c3ee22104bcb4f3b6c4e Mon Sep 17 00:00:00 2001
|
|
|
3de368 |
From: Michael Haggerty <mhagger@alum.mit.edu>
|
|
|
3de368 |
Date: Wed, 25 Mar 2015 22:33:11 +0100
|
|
|
3de368 |
Subject: [PATCH 2/2] resolve_ref_unsafe(): limit the number of "stat_ref"
|
|
|
3de368 |
retries
|
|
|
3de368 |
|
|
|
3de368 |
If there is a broken symlink where a loose reference file is expected,
|
|
|
3de368 |
then the attempt to open() it fails with ENOENT. This error is
|
|
|
3de368 |
misinterpreted to mean that the loose reference file itself has
|
|
|
3de368 |
disappeared due to a race, causing the lookup to be retried. But in
|
|
|
3de368 |
this scenario, the retries all suffer from the same problem, causing
|
|
|
3de368 |
an infinite loop.
|
|
|
3de368 |
|
|
|
3de368 |
So put a limit (of 5) on the number of times that the stat_ref step
|
|
|
3de368 |
can be retried.
|
|
|
3de368 |
|
|
|
3de368 |
Based-on-patch-by: Petr Stodulka <pstodulk@redhat.com>
|
|
|
3de368 |
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
|
|
|
3de368 |
---
|
|
|
3de368 |
refs/files-backend.c | 6 ++++--
|
|
|
3de368 |
refs/refs-internal.h | 6 ++++++
|
|
|
3de368 |
2 files changed, 10 insertions(+), 2 deletions(-)
|
|
|
3de368 |
|
|
|
3de368 |
diff --git a/refs/files-backend.c b/refs/files-backend.c
|
|
|
3de368 |
index d16feb1..245a0b5 100644
|
|
|
3de368 |
--- a/refs/files-backend.c
|
|
|
3de368 |
+++ b/refs/files-backend.c
|
|
|
3de368 |
@@ -1353,6 +1353,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
|
|
|
3de368 |
int fd;
|
|
|
3de368 |
int ret = -1;
|
|
|
3de368 |
int save_errno;
|
|
|
3de368 |
+ int retries = 0;
|
|
|
3de368 |
|
|
|
3de368 |
strbuf_reset(&sb_path);
|
|
|
3de368 |
strbuf_git_path(&sb_path, "%s", refname);
|
|
|
3de368 |
@@ -1390,7 +1391,8 @@ static int files_read_raw_ref(struct ref_store *ref_store,
|
|
|
3de368 |
if (S_ISLNK(st.st_mode)) {
|
|
|
3de368 |
strbuf_reset(&sb_contents);
|
|
|
3de368 |
if (strbuf_readlink(&sb_contents, path, 0) < 0) {
|
|
|
3de368 |
- if (errno == ENOENT || errno == EINVAL)
|
|
|
3de368 |
+ if ((errno == ENOENT || errno == EINVAL) &&
|
|
|
3de368 |
+ retries++ < MAXRETRIES)
|
|
|
3de368 |
/* inconsistent with lstat; retry */
|
|
|
3de368 |
goto stat_ref;
|
|
|
3de368 |
else
|
|
|
3de368 |
@@ -1426,7 +1428,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
|
|
|
3de368 |
*/
|
|
|
3de368 |
fd = open(path, O_RDONLY);
|
|
|
3de368 |
if (fd < 0) {
|
|
|
3de368 |
- if (errno == ENOENT)
|
|
|
3de368 |
+ if (errno == ENOENT && retries++ < MAXRETRIES)
|
|
|
3de368 |
/* inconsistent with lstat; retry */
|
|
|
3de368 |
goto stat_ref;
|
|
|
3de368 |
else
|
|
|
3de368 |
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
|
|
|
3de368 |
index 708b260..37e6b99 100644
|
|
|
3de368 |
--- a/refs/refs-internal.h
|
|
|
3de368 |
+++ b/refs/refs-internal.h
|
|
|
3de368 |
@@ -255,6 +255,12 @@ int rename_ref_available(const char *old_refname, const char *new_refname);
|
|
|
3de368 |
/* We allow "recursive" symbolic refs. Only within reason, though */
|
|
|
3de368 |
#define SYMREF_MAXDEPTH 5
|
|
|
3de368 |
|
|
|
3de368 |
+/*
|
|
|
3de368 |
+ * We allow only MAXRETRIES tries to jump on stat_ref, because of possible
|
|
|
3de368 |
+ * infinite loop
|
|
|
3de368 |
+ */
|
|
|
3de368 |
+#define MAXRETRIES 5
|
|
|
3de368 |
+
|
|
|
3de368 |
/* Include broken references in a do_for_each_ref*() iteration: */
|
|
|
3de368 |
#define DO_FOR_EACH_INCLUDE_BROKEN 0x01
|
|
|
3de368 |
|
|
|
3de368 |
--
|
|
|
3de368 |
2.5.5
|
|
|
3de368 |
|