diff mbox series

[08/23] builtin/submodule--helper: fix leaking remote ref on errors

Message ID d088703d317a8598e1cc4eb068234c105cdeffe6.1726484308.git.ps@pks.im (mailing list archive)
State Superseded
Headers show
Series Memory leak fixes (pt.7) | expand

Commit Message

Patrick Steinhardt Sept. 16, 2024, 11:45 a.m. UTC
When `update_submodule()` fails we return with `die_message()`.
Curiously enough, this causes a memory leak because we use the
`run_process_parallel()` interfaces here, which swap out the die
routine.

Fix the leak by freeing the remote ref.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/submodule--helper.c  | 13 +++++++++----
 t/t7420-submodule-set-url.sh |  1 +
 2 files changed, 10 insertions(+), 4 deletions(-)

Comments

Justin Tobler Sept. 16, 2024, 6:51 p.m. UTC | #1
On 24/09/16 01:45PM, Patrick Steinhardt wrote:
> When `update_submodule()` fails we return with `die_message()`.
> Curiously enough, this causes a memory leak because we use the
> `run_process_parallel()` interfaces here, which swap out the die
> routine.

Naive question, is `update_submodule()` itself being run in parallel
here? Is that why the die routine gets swapped out so a child process
dying is handled differently? Also is it correct to say leaks are not
considered when we "die" normally? 

> Fix the leak by freeing the remote ref.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
Patrick Steinhardt Sept. 17, 2024, 10:19 a.m. UTC | #2
On Mon, Sep 16, 2024 at 01:51:21PM -0500, Justin Tobler wrote:
> On 24/09/16 01:45PM, Patrick Steinhardt wrote:
> > When `update_submodule()` fails we return with `die_message()`.
> > Curiously enough, this causes a memory leak because we use the
> > `run_process_parallel()` interfaces here, which swap out the die
> > routine.
> 
> Naive question, is `update_submodule()` itself being run in parallel
> here? Is that why the die routine gets swapped out so a child process
> dying is handled differently? Also is it correct to say leaks are not
> considered when we "die" normally? 

Hm. Revisiting this patch: my analysis was wrong. It's not the parallel
subsystem that swaps out `die()`, but it's the fact that we call
`die_message()`, which actually doesn't die. It really only prints the
message you would see when we call `die()`, nothing more.

I'll amend the commit message and send out the amended version once
there is more feedback to address.

Patrick
Junio C Hamano Sept. 25, 2024, 8:26 p.m. UTC | #3
Patrick Steinhardt <ps@pks.im> writes:

> On Mon, Sep 16, 2024 at 01:51:21PM -0500, Justin Tobler wrote:
>> On 24/09/16 01:45PM, Patrick Steinhardt wrote:
>> > When `update_submodule()` fails we return with `die_message()`.
>> > Curiously enough, this causes a memory leak because we use the
>> > `run_process_parallel()` interfaces here, which swap out the die
>> > routine.
>> 
>> Naive question, is `update_submodule()` itself being run in parallel
>> here? Is that why the die routine gets swapped out so a child process
>> dying is handled differently? Also is it correct to say leaks are not
>> considered when we "die" normally? 
>
> Hm. Revisiting this patch: my analysis was wrong. It's not the parallel
> subsystem that swaps out `die()`, but it's the fact that we call
> `die_message()`, which actually doesn't die. It really only prints the
> message you would see when we call `die()`, nothing more.
>
> I'll amend the commit message and send out the amended version once
> there is more feedback to address.

So it has been a week and half since the series was posted and it
seems that this is the only thing you might want to touch up.

What's next?  Just have an updated patch [08/23] and nothing else
and be done with it?  A v2 round of 23-patch series hopefully will
see somebody other than Justin and I lend an extra set of eyes to
double check before we merge it to 'next'?

Thanks.
Patrick Steinhardt Sept. 26, 2024, 11:58 a.m. UTC | #4
On Wed, Sep 25, 2024 at 01:26:17PM -0700, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> 
> > On Mon, Sep 16, 2024 at 01:51:21PM -0500, Justin Tobler wrote:
> >> On 24/09/16 01:45PM, Patrick Steinhardt wrote:
> >> > When `update_submodule()` fails we return with `die_message()`.
> >> > Curiously enough, this causes a memory leak because we use the
> >> > `run_process_parallel()` interfaces here, which swap out the die
> >> > routine.
> >> 
> >> Naive question, is `update_submodule()` itself being run in parallel
> >> here? Is that why the die routine gets swapped out so a child process
> >> dying is handled differently? Also is it correct to say leaks are not
> >> considered when we "die" normally? 
> >
> > Hm. Revisiting this patch: my analysis was wrong. It's not the parallel
> > subsystem that swaps out `die()`, but it's the fact that we call
> > `die_message()`, which actually doesn't die. It really only prints the
> > message you would see when we call `die()`, nothing more.
> >
> > I'll amend the commit message and send out the amended version once
> > there is more feedback to address.
> 
> So it has been a week and half since the series was posted and it
> seems that this is the only thing you might want to touch up.
> 
> What's next?  Just have an updated patch [08/23] and nothing else
> and be done with it?  A v2 round of 23-patch series hopefully will
> see somebody other than Justin and I lend an extra set of eyes to
> double check before we merge it to 'next'?

Makes sense, let's do it this way! I've sent a v2 a couple minutes ago.

Patrick
diff mbox series

Patch

diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index ff1376f69fc..a9bd93a7856 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -2648,15 +2648,20 @@  static int update_submodule(struct update_data *update_data)
 
 		if (!update_data->nofetch) {
 			if (fetch_in_submodule(update_data->sm_path, update_data->depth,
-					      0, NULL))
+					      0, NULL)) {
+				free(remote_ref);
 				return die_message(_("Unable to fetch in submodule path '%s'"),
 						   update_data->sm_path);
+			}
 		}
 
 		if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,
-					     remote_ref, &update_data->oid))
-			return die_message(_("Unable to find %s revision in submodule path '%s'"),
-					   remote_ref, update_data->sm_path);
+					     remote_ref, &update_data->oid)) {
+			ret = die_message(_("Unable to find %s revision in submodule path '%s'"),
+					  remote_ref, update_data->sm_path);
+			free(remote_ref);
+			return ret;
+		}
 
 		free(remote_ref);
 	}
diff --git a/t/t7420-submodule-set-url.sh b/t/t7420-submodule-set-url.sh
index bf7f15ee797..d7fe910bbe1 100755
--- a/t/t7420-submodule-set-url.sh
+++ b/t/t7420-submodule-set-url.sh
@@ -10,6 +10,7 @@  as expected.
 '
 
 TEST_NO_CREATE_REPO=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '