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

Re: [PATCH v2 3/3] Revert "pack-objects: lazily set up "struct rev_info", don't leak"

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Nov 28, 2022, 15:27 UTC
Message-ID
<221128.861qpnkrd3.gmgdl@evledraar.gmail.com>
In-Reply-To
<9bea523d-93d1-953b-a136-3f00844c880a@web.de>
On Mon, Nov 28 2022, René Scharfe wrote:
Show 107 quoted lines
> Am 28.11.2022 um 13:24 schrieb Ævar Arnfjörð Bjarmason:
>>
>> On Mon, Nov 28 2022, Ævar Arnfjörð Bjarmason wrote:
>>
>> René:
>>
>>> On Mon, Nov 28 2022, René Scharfe wrote:
>>>
>>>> Am 28.11.2022 um 11:03 schrieb Junio C Hamano:
>>>>> René Scharfe <l.s.r@web.de> writes:
>>>>>
>>>>>> This reverts commit 5cb28270a1ff94a0a23e67b479bbbec3bc993518.
>>>>>>
>>>>>> 5cb28270a1 (pack-objects: lazily set up "struct rev_info", don't leak,
>>>>>> 2022-03-28) avoided leaking rev_info allocations in many cases by
>>>>>> calling repo_init_revisions() only when the .filter member was actually
>>>>>> needed, but then still leaking it.  That was fixed later by 2108fe4a19
>>>>>> (revisions API users: add straightforward release_revisions(),
>>>>>> 2022-04-13), making the reverted commit unnecessary.
>>>>>
>>>>> Hmph, with this merged, 'seen' breaks linux-leaks job in a strange
>>>>> way.
>>>>>
>>>>> https://github.com/git/git/actions/runs/3563546608/jobs/5986458300#step:5:3917
>>>>>
>>>>> Does anybody want to help looking into it?
>>>
>>> [I see we crossed E-Mails]:
>>> https://lore.kernel.org/git/221128.868rjvmi3l.gmgdl@evledraar.gmail.com/
>>>
>>>> The patch exposes that release_revisions() leaks the diffopt allocations
>>>> as we're yet to address the TODO added by 54c8a7c379 (revisions API: add
>>>> a TODO for diff_free(&revs->diffopt), 2022-04-14).
>>>
>>> That's correct, and we have that leak in various places in our codebase,
>>> but per the above side-thread I think this is primarily exposing that
>>> we're setting up the "struct rev_info" with your change when we don't
>>> need to. Why can't we just skip it?
>>>
>>> Yeah, if we do set it up we'll run into an outstanding leak, and that
>>> should also be fixed (I have some local patches...), but the other cases
>>> I know of where we'll leak that data is where we're actually using the
>>> "struct rev_info".
>>>
>>> I haven't tried tearing your change apart to poke at it myself, and
>>> maybe there's some really good reason for why you can't separate getting
>>> rid of the J.5.7 dependency and removing the lazy-init.
>>>
>>>> The patch below plugs it locally.
>>>>
>>>> --- >8 ---
>>>> Subject: [PATCH 4/3] fixup! revision: free diffopt in release_revisions()
>>>>
>>>> Signed-off-by: René Scharfe <l.s.r@web.de>
>>>> ---
>>>>  builtin/pack-objects.c | 1 +
>>>>  1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
>>>> index 3e74fbb0cd..a47a3f0fba 100644
>>>> --- a/builtin/pack-objects.c
>>>> +++ b/builtin/pack-objects.c
>>>> @@ -4462,6 +4462,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
>>>>  	} else {
>>>>  		get_object_list(&revs, rp.nr, rp.v);
>>>>  	}
>>>> +	diff_free(&revs.diffopt);
>>>>  	release_revisions(&revs);
>>>>  	cleanup_preferred_base();
>>>>  	if (include_tag && nr_result)
>>>
>>> So, the main motivation for the change was paranoia that a compiler or
>>> platform might show up without J.5.7 support and that would bite us, but
>>> we're now adding a double-free-in-waiting?
>>>
>>> I think we're both a bit paranoid, but clearly have different
>>> paranoia-priorities :)
>>>
>>> If we do end up with some hack like this instead of fixing the
>>> underlying problem I'd much prefer that such a hack just be an UNLEAK()
>>> here.
>>>
>>> I.e. we have a destructor for "revs.*" already, let's not bypass it and
>>> start freeing things from under it, which will result in a double-free
>>> if we forget this callsite once the TODO in 54c8a7c379 is addressed.
>>>
>>> As you'd see if you made release_revisions() simply call
>>> diff_free(&revs.diffopt) doing so would reveal some really gnarly edge
>>> cases.
>>>
>>> I haven't dug into this one, but offhand I'm not confident in saying
>>> that this isn't exposing us to some aspect of that gnarlyness (maybe
>>> not, it's been a while since I looked).
>>>
>>> (IIRC some of the most gnarly edge cases will only show up as CI
>>> failures on Windows, to do with the ordering of when we'll fclose()
>>> files hanging off that "diffopt").
>>
>> This squashed into 3/3 seems to me to be a proper fix to a change that
>> wants to refactor the code for non-J.5.7 compatibility. I.e. this just
>> does the data<->fp casting part of the change, without refactoring the
>> "lazy init".
>
> That works, but lazy code is more complicated and there is no benefit
> here -- eager allocations are not noticably slow or big.  Laziness
> hides leaks in corners, i.e. requiring invocations with uncommon
> options to trigger them.

Yes, sometimes it's easier to just set everything up at the beginning. As for hiding leaks I think the empirical data here is going against that, i.e. your change introduced a leak.

I don't think it's realistic that we'll have the side that assigns to "have_revs" drift from the corresponding code in cmd_pack_objects().

Show 5 quoted lines
>> But I think you should check this a bit more carefully. Your 3/3 says
>> that your change "mak[es] the reverted commit unnecessary"
>
> No, it says that _your_ change 2108fe4a19 (revisions API users: add
> straightforward release_revisions(), 2022-04-13) made it unnecessary.

Yes, I'm saying that's not correct, because if you run the command that 5cb28270a1 prominently notes we'll now leak with this revert:

	echo e83c5163316f89bfbde7d9ab23ca2e25604af290 | ./git pack-objects initial

But yes with just 5cb28270a1 didn't add release_revisions(), that came shortly afterwards in 2108fe4a19.

Show 8 quoted lines
>> , but as I
>> noted if you'd run the command that commit shows, you'd have seen you're
>> re-introducing the leak it fixed. So I wonder what else has been missed
>> here.
>
> 5cb28270a1 (pack-objects: lazily set up "struct rev_info", don't leak,
> 2022-03-28) did not plug the leak.  It only moved it to the corner that
> handles the --filter option.

I think we're using "the leak" here differently. I mean callstacks that LeakSanitizer emits & tests we have that do & don't pass with SANITIZE=leak.

But yes, there may be multiple paths through a function, some of which leak, some of which don't. I'm not saying that the entire set of API features that builtin/pack-objects.c uses in the revision API is leak-free.

> That leak is only interesting to Git developers and harmless for users.
> But if the goal is to become free of trivial leaks in order to allow
> using tools like LeakSanitizer to find real ones then pushing them into
> the shadows not yet reached by our test coverage won't help for long.
It's clearly helping in this case, as our CI had multiple failing tests.
Show 8 quoted lines
>> I vaguely recall that one reason I ended up with that J.5.7 dependency
>> was because there was an objection to mocking up the "struct option" as
>> I'm doing here. I.e. here we assume that the
>> opt_parse_list_objects_filter() is only ever going to care about the
>> "value" member.
>
> It's probably fine, but unnecessarily complicated compared to calling
> repo_init_revisions() eagerly.

I'm leaving aside the question of whether we should go for some version of the refactoring in your 3/3.

What I am saying is that such refactoring should be split up from the more narrow bug fix to the existing code. I.e. this as a replacement for your 3/3 is all that's needed to pass the test you're adding in 2/3.

-- >8 --
From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= <l.s.r@web.de>
Subject: [PATCH] pack-objects: support multiple --filter options again

5cb28270a1f (pack-objects: lazily set up "struct rev_info", don't leak, 2022-03-28) broke support for multiple --filter options by calling repo_init_revisions() every time "--filter" was seen. Instead we should only do so the first time, and subsequently append to the existing filter data.

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/pack-objects.c                 | 3 ++-
 t/t5317-pack-objects-filter-objects.sh | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 573d0b20b76..c702c09dd45 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -4158,7 +4158,8 @@ static struct list_objects_filter_options *po_filter_revs_init(void *value)
 {
 	struct po_filter_data *data = value;
 
-	repo_init_revisions(the_repository, &data->revs, NULL);
+	if (!data->have_revs)
+		repo_init_revisions(the_repository, &data->revs, NULL);
 	data->have_revs = 1;
 
 	return &data->revs.filter;
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 25faebaada8..5b707d911b5 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -265,7 +265,7 @@ test_expect_success 'verify normal and blob:limit packfiles have same commits/tr
 	test_cmp expected observed
 '
 
-test_expect_failure 'verify small limit and big limit results in small limit' '
+test_expect_success 'verify small limit and big limit results in small limit' '
 	git -C r2 ls-files -s large.1000 >ls_files_result &&
 	test_parse_ls_files_stage_oids <ls_files_result |
 	sort >expected &&
-- 
2.39.0.rc0.993.g0c499e58e3b
Previous: René ScharfeNext: René Scharfe
Message 24 of 52 in “pack-objects: fix and simplify --filter handling”
  1. 0/3 pack-objects: fix and simplify --filter handlingRené Scharfe, Nov 12, 2022
  2. 1/3 pack-objects: fix handling of multiple --filter optionsRené Scharfe, Nov 12, 2022
  3. Ævar Arnfjörð BjarmasonNov 12, 2022
  4. René ScharfeNov 13, 2022
  5. Jeff KingNov 12, 2022
  6. Taylor BlauNov 13, 2022
  7. Jeff KingNov 13, 2022
  8. René ScharfeNov 13, 2022
  9. 2/3 pack-object: simplify --filter handlingRené Scharfe, Nov 12, 2022
  10. Ævar Arnfjörð BjarmasonNov 12, 2022
  11. Jeff KingNov 12, 2022
  12. Jeff KingNov 13, 2022
  13. René ScharfeNov 13, 2022
  14. 3/3 list-objects-filter: remove OPT_PARSE_LIST_OBJECTS_FILTER_INIT()René Scharfe, Nov 12, 2022
  15. 0/3 pack-objects: fix and simplify --filter handlingRené Scharfe, Nov 20, 2022
  16. 2/3 t5317: demonstrate failure to handle multiple --filter optionsRené Scharfe, Nov 20, 2022
  17. 1/3 t5317: stop losing return codes of git ls-filesRené Scharfe, Nov 20, 2022
  18. 3/3 Revert "pack-objects: lazily set up "struct rev_info", don't leak"René Scharfe, Nov 20, 2022
  19. Junio C HamanoNov 28, 2022
  20. René ScharfeNov 28, 2022
  21. Ævar Arnfjörð BjarmasonNov 28, 2022
  22. Ævar Arnfjörð BjarmasonNov 28, 2022
  23. René ScharfeNov 28, 2022
  24. Ævar Arnfjörð BjarmasonNov 28, 2022
  25. René ScharfeNov 28, 2022
  26. Ævar Arnfjörð BjarmasonNov 28, 2022
  27. René ScharfeNov 28, 2022
  28. René ScharfeNov 28, 2022
  29. Ævar Arnfjörð BjarmasonNov 28, 2022
  30. René ScharfeNov 28, 2022
  31. Jeff KingNov 29, 2022
  32. Junio C HamanoNov 29, 2022
  33. Ævar Arnfjörð BjarmasonNov 29, 2022
  34. Ævar Arnfjörð BjarmasonNov 29, 2022
  35. René ScharfeNov 29, 2022
  36. Ævar Arnfjörð BjarmasonNov 28, 2022
  37. Ævar Arnfjörð BjarmasonNov 28, 2022
  38. t5314: check exit code of "rev-parse"Ævar Arnfjörð Bjarmason, Nov 28, 2022
  39. René ScharfeNov 28, 2022
  40. t5314: check exit code of "git"Ævar Arnfjörð Bjarmason, Nov 28, 2022
  41. Jeff KingNov 22, 2022
  42. 0/5 pack-objects: fix and simplify --filter handlingRené Scharfe, Nov 29, 2022
  43. 1/5 t5317: stop losing return codes of git ls-filesRené Scharfe, Nov 29, 2022
  44. 2/5 t5317: demonstrate failure to handle multiple --filter optionsRené Scharfe, Nov 29, 2022
  45. 3/5 pack-objects: fix handling of multiple --filter optionsRené Scharfe, Nov 29, 2022
  46. Junio C HamanoNov 30, 2022
  47. René ScharfeNov 30, 2022
  48. 4/5 pack-objects: simplify --filter handlingRené Scharfe, Nov 29, 2022
  49. Ævar Arnfjörð BjarmasonNov 29, 2022
  50. René ScharfeNov 30, 2022
  51. 5/5 list-objects-filter: remove OPT_PARSE_LIST_OBJECTS_FILTER_INIT()René Scharfe, Nov 29, 2022
  52. Junio C HamanoNov 30, 2022

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.