git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/2] resolve_ref_unsafe(): limit the number of "stat_ref" retries

From
Petr Stodulka <pstodulk@redhat.com>
Date
Oct 14, 2016, 13:20 UTC
Message-ID
<855173d3-12b1-5b6c-4910-f19a8f3395b7@redhat.com>
In-Reply-To
<1476451012-9925-3-git-send-email-pstodulk@redhat.com>

FYI, I modified the patch slightly.

On 14.10.2016 15:16, Petr Stodulka wrote:
Show 68 quoted lines
> From: Michael Haggerty <mhagger@alum.mit.edu>
> 
> If there is a broken symlink where a loose reference file is expected,
> then the attempt to open() it fails with ENOENT. This error is
> misinterpreted to mean that the loose reference file itself has
> disappeared due to a race, causing the lookup to be retried. But in
> this scenario, the retries all suffer from the same problem, causing
> an infinite loop.
> 
> So put a limit (of 5) on the number of times that the stat_ref step
> can be retried.
> 
> Based-on-patch-by: Petr Stodulka <pstodulk@redhat.com>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
>  refs/files-backend.c | 6 ++++--
>  refs/refs-internal.h | 6 ++++++
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index d16feb1..245a0b5 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -1353,6 +1353,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
>  	int fd;
>  	int ret = -1;
>  	int save_errno;
> +	int retries = 0;
>  
>  	*type = 0;
>  	strbuf_reset(&sb_path);
> @@ -1390,7 +1391,8 @@ static int files_read_raw_ref(struct ref_store *ref_store,
>  	if (S_ISLNK(st.st_mode)) {
>  		strbuf_reset(&sb_contents);
>  		if (strbuf_readlink(&sb_contents, path, 0) < 0) {
> -			if (errno == ENOENT || errno == EINVAL)
> +			if ((errno == ENOENT || errno == EINVAL) &&
> +				retries++ < MAXRETRIES) 
>  				/* inconsistent with lstat; retry */
>  				goto stat_ref;
>  			else
> @@ -1426,7 +1428,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
>  	 */
>  	fd = open(path, O_RDONLY);
>  	if (fd < 0) {
> -		if (errno == ENOENT)
> +		if (errno == ENOENT && retries++ < MAXRETRIES)
>  			/* inconsistent with lstat; retry */
>  			goto stat_ref;
>  		else
> diff --git a/refs/refs-internal.h b/refs/refs-internal.h
> index 708b260..37e6b99 100644
> --- a/refs/refs-internal.h
> +++ b/refs/refs-internal.h
> @@ -255,6 +255,12 @@ int rename_ref_available(const char *old_refname, const char *new_refname);
>  /* We allow "recursive" symbolic refs. Only within reason, though */
>  #define SYMREF_MAXDEPTH 5
>  
> +/* 
> + * We allow only MAXRETRIES tries to jump on stat_ref, because of possible
> + * infinite loop
> + */
> +#define MAXRETRIES 5
> +
>  /* Include broken references in a do_for_each_ref*() iteration: */
>  #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
>  
> 
Previous: Petr StodulkaNext: Jeff King
Message 4 of 6 in “infinite loop in "git ls-tree" for broken symlink”
  1. 0/2 infinite loop in "git ls-tree" for broken symlinkPetr Stodulka, Oct 14, 2016
  2. 1/2 Add test for ls-tree with broken symlink under refs/headsPetr Stodulka, Oct 14, 2016
  3. 2/2 resolve_ref_unsafe(): limit the number of "stat_ref" retriesPetr Stodulka, Oct 14, 2016
  4. Petr StodulkaOct 14, 2016
  5. Jeff KingOct 14, 2016
  6. Petr StodulkaOct 14, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.