Download raw body.
memleak in commit_graph
I'm chasing a memleak in gotwebd' blame page and landed here. A dummy
commit graph loop seems to leak a bit so chances are that what I'm
seeing in gotwebd are due to the commit graph loop (via blame.c)
With "dummy" loop I mean more or less:
got_commit_graph_open(...);
got_commit_graph_iter_start(...);
for (;;) {
err = got_commit_graph_iter_next(...);
if (err)
break;
}
got_commit_graph_close(graph);
ran in an infinite loop to spot leaks.
I managed to find something (the tailq leak fix in
got_commit_graph_close was actually suggested by Stefan on IRC) but
it's not the whole story, there are still leaks. I'm sending what I
have for the moment.
in fetch_commits_from_open_branches we might leak some `new_node's
allocated in the arg struct. In fact, if i'm reading the code
correctly, every time that we don't end up calling
add_node_to_iter_list we're leaking a node.
the change to add_branch_tip fixes a leak if add_node fails and
clarify one bit: if add_node succeeds new_node is not NULL so can drop
the ternary.
regress is happy. OK/further ideas for leaks in here?
diff /home/op/w/got
commit - 442ede73eadb025cdc45bede186bf31aee869dad
path + /home/op/w/got
blob - 01dc8264285fe44769741f2870eda27d3d1e6b16
file + lib/commit_graph.c
--- lib/commit_graph.c
+++ lib/commit_graph.c
@@ -446,10 +446,12 @@ add_branch_tip(struct got_object_id *commit_id, void *
return err;
err = add_node(&new_node, a->graph, commit_id, a->repo);
- if (err)
+ if (err) {
+ got_object_commit_close(commit);
return err;
+ }
- a->tips[a->ntips].commit_id = new_node ? &new_node->id : NULL;
+ a->tips[a->ntips].commit_id = &new_node->id;
a->tips[a->ntips].commit = commit;
a->tips[a->ntips].new_node = new_node;
a->ntips++;
@@ -518,22 +520,33 @@ fetch_commits_from_open_branches(struct got_commit_gra
break;
continue;
}
- if (changed)
+ if (changed) {
add_node_to_iter_list(graph, new_node,
got_object_commit_get_committer_time(commit));
+ arg.tips[i].new_node = NULL;
+ }
err = advance_branch(graph, commit_id, commit, repo);
if (err)
break;
}
done:
- for (i = 0; i < arg.ntips; i++)
+ for (i = 0; i < arg.ntips; i++) {
got_object_commit_close(arg.tips[i].commit);
+ free(arg.tips[i].new_node);
+ }
return err;
}
void
got_commit_graph_close(struct got_commit_graph *graph)
{
+ struct got_commit_graph_node *node;
+
+ while ((node = TAILQ_FIRST(&graph->iter_list))) {
+ TAILQ_REMOVE(&graph->iter_list, node, entry);
+ free(node);
+ }
+
if (graph->open_branches)
got_object_idset_free(graph->open_branches);
if (graph->node_ids)
memleak in commit_graph