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

Re: [PATCH v2 1/2] refs/files-backend: add longer-scoped copy of string to list

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Aug 29, 2017, 08:33 UTC
Message-ID
<49134978-130d-ff43-e3c6-bde211710064@alum.mit.edu>
In-Reply-To
<7f6617d2f1df9ee6746e4cbc41dc84bdb7788574.1503951733.git.martin.agren@gmail.com>
On 08/28/2017 10:32 PM, Martin Ågren wrote:
Show 46 quoted lines
> split_symref_update() receives a string-pointer `referent` and adds it
> to the list of `affected_refnames`. The list simply holds on to the
> pointers it is given, it does not copy the strings and it never frees
> them. The `referent` string in split_symref_update() belongs to a string
> buffer in the caller. After we return, the string will be leaked.
> 
> In the next patch, we want to properly release the string buffer in the
> caller, but we can't safely do so until we've made sure that
> `affected_refnames` will not be holding on to a pointer to the string.
> We could configure the list to handle its own resources, but it would
> mean some alloc/free-churning. The list is already handling other
> strings (through other code paths) which we do not need to worry about,
> and we'd be memory-churning those strings too, completely unnecessary.
> 
> Observe that split_symref_update() creates a `new_update`-object and
> that `new_update->refname` is then a copy of `referent`. The difference
> is, this copy will be freed, and it will be freed *after*
> `affected_refnames` has been cleared.
> 
> Rearrange the handling of `referent`, so that we don't add it directly
> to `affected_refnames`. Instead, first just check whether `referent`
> exists in the string list, and later add `new_update->refname`.
> 
> Helped-by: Michael Haggerty <mhagger@alum.mit.edu>
> Signed-off-by: Martin Ågren <martin.agren@gmail.com>
> ---
> Thanks Junio and Michael for your comments on the first version. This
> first patch is now completely different and much much better (thanks
> Michael!). The commit message should also be better (sorry Junio...).
> The second one has a new commit message, but the diff is the same.
> 
> Martin
> 
>  refs/files-backend.c | 16 ++++++++++++----
>  1 file changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index 5cca55510..bdb0e22e5 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -2140,13 +2140,12 @@ static int split_symref_update(struct files_ref_store *refs,
>  
>  	/*
>  	 * First make sure that referent is not already in the
> -	 * transaction. This insertion is O(N) in the transaction
> +	 * transaction. This check is O(N) in the transaction

The check is not O(N); it is O(lg N) because it is implemented via a binary search in the (sorted) `affected_refnames`. The insertion below is still O(N), because it has to shift entries later in the list to the right to make room for the new entry.

Show 24 quoted lines
>  	 * size, but it happens at most once per symref in a
>  	 * transaction.
>  	 */
> -	item = string_list_insert(affected_refnames, referent);
> -	if (item->util) {
> -		/* An entry already existed */
> +	if (string_list_has_string(affected_refnames, referent)) {
> +		/* An entry already exists */
>  		strbuf_addf(err,
>  			    "multiple updates for '%s' (including one "
>  			    "via symref '%s') are not allowed",
> @@ -2181,6 +2180,15 @@ static int split_symref_update(struct files_ref_store *refs,
>  	update->flags |= REF_LOG_ONLY | REF_NODEREF;
>  	update->flags &= ~REF_HAVE_OLD;
>  
> +	/*
> +	 * Add the referent. This insertion is O(N) in the transaction
> +	 * size, but it happens at most once per symref in a
> +	 * transaction. Make sure to add new_update->refname, which will
> +	 * be valid as long as affected_refnames is in use, and NOT
> +	 * referent, which might soon be freed by our caller.
> +	 */
> +	item = string_list_insert(affected_refnames, new_update->refname);
> +	assert(!item->util);
We generally avoid using `assert()`. It would be preferable to use
        if (item->util)
                BUG("%s unexpectedly found in affected_refnames",
new_update->refname);
>  	item->util = new_update;
>  
>  	return 0;
> 
Otherwise, looks good!
Michael
Previous: Martin ÅgrenNext: Martin Ågren
Message 8 of 34 in “refs/files-backend: duplicate strings added to affected_refnames”
  1. 1/2 refs/files-backend: duplicate strings added to affected_refnamesMartin Ågren, Aug 25, 2017
  2. 2/2 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Aug 25, 2017
  3. Junio C HamanoAug 25, 2017
  4. Martin ÅgrenAug 26, 2017
  5. Michael HaggertyAug 28, 2017
  6. Martin ÅgrenAug 28, 2017
  7. 1/2 refs/files-backend: add longer-scoped copy of string to listMartin Ågren, Aug 28, 2017
  8. Michael HaggertyAug 29, 2017
  9. 2/2 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Aug 28, 2017
  10. Michael HaggertyAug 29, 2017
  11. Martin ÅgrenAug 29, 2017
  12. 1/3 refs/files-backend: add longer-scoped copy of string to listMartin Ågren, Aug 29, 2017
  13. Michael HaggertyAug 30, 2017
  14. Martin ÅgrenAug 30, 2017
  15. Junio C HamanoSep 5, 2017
  16. Martin ÅgrenSep 5, 2017
  17. Jeff KingSep 5, 2017
  18. Junio C HamanoSep 5, 2017
  19. Martin ÅgrenSep 6, 2017
  20. Junio C HamanoSep 6, 2017
  21. Jeff KingSep 6, 2017
  22. 0/4 Rerolling ma/split-symref-update-fixMartin Ågren, Sep 9, 2017
  23. 1/4 refs/files-backend: add longer-scoped copy of string to listMartin Ågren, Sep 9, 2017
  24. 2/4 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Sep 9, 2017
  25. 3/4 refs/files-backend: correct return value in lock_ref_for_updateMartin Ågren, Sep 9, 2017
  26. 4/4 refs/files-backend: add `refname`, not "HEAD", to listMartin Ågren, Sep 9, 2017
  27. Jeff KingSep 9, 2017
  28. Jeff KingSep 5, 2017
  29. Michael HaggertySep 5, 2017
  30. Jeff KingSep 5, 2017
  31. 2/3 refs/files-backend: fix memory leak in lock_ref_for_updateMartin Ågren, Aug 29, 2017
  32. Jeff KingSep 5, 2017
  33. Martin ÅgrenSep 5, 2017
  34. 3/3 refs/files-backend: correct return value in lock_ref_for_updateMartin Ågren, Aug 29, 2017

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.