Skip to content

Commit a5aecb2

Browse files
pks-tgitster
authored andcommitted
diff: improve lifecycle management of diff queues
The lifecycle management of diff queues is somewhat confusing: - For most of the part this can be attributed to `DIFF_QUEUE_CLEAR()`, which does not release any memory but rather initializes the queue, only. This is in contrast to our common naming schema, where "clearing" means that we release underlying memory and then re-initialize the data structure such that it is ready to use. - A second offender is `diff_free_queue()`, which does not free the queue structure itself. It is rather a release-style function. Refactor the code to make things less confusing. `DIFF_QUEUE_CLEAR()` is replaced by `DIFF_QUEUE_INIT` and `diff_queue_init()`, while `diff_free_queue()` is replaced by `diff_queue_release()`. While on it, adapt callsites where we call `DIFF_QUEUE_CLEAR()` with the intent to release underlying memory to instead call `diff_queue_clear()` to fix memory leaks. This memory leak is exposed by t4211, but plugging it alone does not make the whole test suite pass. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fdf972a commit a5aecb2

10 files changed

+32
-47
lines changed

bloom.c

+1-7
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
476476
*last_slash = '\0';
477477

478478
} while (*path);
479-
480-
diff_free_filepair(diff_queued_diff.queue[i]);
481479
}
482480

483481
if (hashmap_get_size(&pathmap) > settings->max_changed_paths) {
@@ -508,8 +506,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
508506
cleanup:
509507
hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry);
510508
} else {
511-
for (i = 0; i < diff_queued_diff.nr; i++)
512-
diff_free_filepair(diff_queued_diff.queue[i]);
513509
init_truncated_large_filter(filter, settings->hash_version);
514510

515511
if (computed)
@@ -519,9 +515,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
519515
if (computed)
520516
*computed |= BLOOM_COMPUTED;
521517

522-
free(diff_queued_diff.queue);
523-
DIFF_QUEUE_CLEAR(&diff_queued_diff);
524-
518+
diff_queue_clear(&diff_queued_diff);
525519
return filter;
526520
}
527521

diff.c

+12-10
Original file line numberDiff line numberDiff line change
@@ -5983,11 +5983,18 @@ void diff_free_filepair(struct diff_filepair *p)
59835983
free(p);
59845984
}
59855985

5986-
void diff_free_queue(struct diff_queue_struct *q)
5986+
void diff_queue_init(struct diff_queue_struct *q)
5987+
{
5988+
struct diff_queue_struct blank = DIFF_QUEUE_INIT;
5989+
memcpy(q, &blank, sizeof(*q));
5990+
}
5991+
5992+
void diff_queue_clear(struct diff_queue_struct *q)
59875993
{
59885994
for (int i = 0; i < q->nr; i++)
59895995
diff_free_filepair(q->queue[i]);
59905996
free(q->queue);
5997+
diff_queue_init(q);
59915998
}
59925999

59936000
const char *diff_aligned_abbrev(const struct object_id *oid, int len)
@@ -6551,8 +6558,7 @@ int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int
65516558
struct diff_queue_struct *q = &diff_queued_diff;
65526559
int result = diff_get_patch_id(options, oid, diff_header_only);
65536560

6554-
diff_free_queue(q);
6555-
DIFF_QUEUE_CLEAR(q);
6561+
diff_queue_clear(q);
65566562

65576563
return result;
65586564
}
@@ -6835,8 +6841,7 @@ void diff_flush(struct diff_options *options)
68356841
}
68366842

68376843
free_queue:
6838-
diff_free_queue(q);
6839-
DIFF_QUEUE_CLEAR(q);
6844+
diff_queue_clear(q);
68406845
diff_free(options);
68416846

68426847
/*
@@ -6867,9 +6872,7 @@ static void diffcore_apply_filter(struct diff_options *options)
68676872
{
68686873
int i;
68696874
struct diff_queue_struct *q = &diff_queued_diff;
6870-
struct diff_queue_struct outq;
6871-
6872-
DIFF_QUEUE_CLEAR(&outq);
6875+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
68736876

68746877
if (!options->filter)
68756878
return;
@@ -6962,8 +6965,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
69626965
{
69636966
int i;
69646967
struct diff_queue_struct *q = &diff_queued_diff;
6965-
struct diff_queue_struct outq;
6966-
DIFF_QUEUE_CLEAR(&outq);
6968+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
69676969

69686970
for (i = 0; i < q->nr; i++) {
69696971
struct diff_filepair *p = q->queue[i];

diffcore-break.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ static int should_break(struct repository *r,
131131
void diffcore_break(struct repository *r, int break_score)
132132
{
133133
struct diff_queue_struct *q = &diff_queued_diff;
134-
struct diff_queue_struct outq;
134+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
135135

136136
/* When the filepair has this much edit (insert and delete),
137137
* it is first considered to be a rewrite and broken into a
@@ -178,8 +178,6 @@ void diffcore_break(struct repository *r, int break_score)
178178
if (!merge_score)
179179
merge_score = DEFAULT_MERGE_SCORE;
180180

181-
DIFF_QUEUE_CLEAR(&outq);
182-
183181
for (i = 0; i < q->nr; i++) {
184182
struct diff_filepair *p = q->queue[i];
185183
int score;
@@ -275,11 +273,9 @@ static void merge_broken(struct diff_filepair *p,
275273
void diffcore_merge_broken(void)
276274
{
277275
struct diff_queue_struct *q = &diff_queued_diff;
278-
struct diff_queue_struct outq;
276+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
279277
int i, j;
280278

281-
DIFF_QUEUE_CLEAR(&outq);
282-
283279
for (i = 0; i < q->nr; i++) {
284280
struct diff_filepair *p = q->queue[i];
285281
if (!p)

diffcore-pickaxe.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
182182
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
183183
{
184184
int i;
185-
struct diff_queue_struct outq;
186-
187-
DIFF_QUEUE_CLEAR(&outq);
185+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
188186

189187
if (o->pickaxe_opts & DIFF_PICKAXE_ALL) {
190188
/* Showing the whole changeset if needle exists */

diffcore-rename.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ void diffcore_rename_extended(struct diff_options *options,
13881388
int detect_rename = options->detect_rename;
13891389
int minimum_score = options->rename_score;
13901390
struct diff_queue_struct *q = &diff_queued_diff;
1391-
struct diff_queue_struct outq;
1391+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
13921392
struct diff_score *mx;
13931393
int i, j, rename_count, skip_unmodified = 0;
13941394
int num_destinations, dst_cnt;
@@ -1638,7 +1638,6 @@ void diffcore_rename_extended(struct diff_options *options,
16381638
* are recorded in rename_dst. The original list is still in *q.
16391639
*/
16401640
trace2_region_enter("diff", "write back to queue", options->repo);
1641-
DIFF_QUEUE_CLEAR(&outq);
16421641
for (i = 0; i < q->nr; i++) {
16431642
struct diff_filepair *p = q->queue[i];
16441643
struct diff_filepair *pair_to_free = NULL;

diffcore-rotate.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
void diffcore_rotate(struct diff_options *opt)
1111
{
1212
struct diff_queue_struct *q = &diff_queued_diff;
13-
struct diff_queue_struct outq;
13+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
1414
int rotate_to, i;
1515

1616
if (!q->nr)
@@ -31,7 +31,6 @@ void diffcore_rotate(struct diff_options *opt)
3131
return;
3232
}
3333

34-
DIFF_QUEUE_CLEAR(&outq);
3534
rotate_to = i;
3635

3736
for (i = rotate_to; i < q->nr; i++)

diffcore.h

+4-6
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,16 @@ struct diff_queue_struct {
153153
int nr;
154154
};
155155

156-
#define DIFF_QUEUE_CLEAR(q) \
157-
do { \
158-
(q)->queue = NULL; \
159-
(q)->nr = (q)->alloc = 0; \
160-
} while (0)
156+
#define DIFF_QUEUE_INIT { 0 }
157+
158+
void diff_queue_init(struct diff_queue_struct *q);
159+
void diff_queue_clear(struct diff_queue_struct *q);
161160

162161
extern struct diff_queue_struct diff_queued_diff;
163162
struct diff_filepair *diff_queue(struct diff_queue_struct *,
164163
struct diff_filespec *,
165164
struct diff_filespec *);
166165
void diff_q(struct diff_queue_struct *, struct diff_filepair *);
167-
void diff_free_queue(struct diff_queue_struct *q);
168166

169167
/* dir_rename_relevance: the reason we want rename information for a dir */
170168
enum dir_rename_relevance {

line-log.c

+7-8
Original file line numberDiff line numberDiff line change
@@ -787,15 +787,14 @@ static void move_diff_queue(struct diff_queue_struct *dst,
787787
struct diff_queue_struct *src)
788788
{
789789
assert(src != dst);
790-
memcpy(dst, src, sizeof(struct diff_queue_struct));
791-
DIFF_QUEUE_CLEAR(src);
790+
memcpy(dst, src, sizeof(*dst));
791+
diff_queue_init(src);
792792
}
793793

794794
static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletions)
795795
{
796796
int i;
797-
struct diff_queue_struct outq;
798-
DIFF_QUEUE_CLEAR(&outq);
797+
struct diff_queue_struct outq = DIFF_QUEUE_INIT;
799798

800799
for (i = 0; i < diff_queued_diff.nr; i++) {
801800
struct diff_filepair *p = diff_queued_diff.queue[i];
@@ -850,12 +849,12 @@ static void queue_diffs(struct line_log_data *range,
850849
clear_pathspec(&opt->pathspec);
851850
parse_pathspec_from_ranges(&opt->pathspec, range);
852851
}
853-
DIFF_QUEUE_CLEAR(&diff_queued_diff);
852+
diff_queue_clear(&diff_queued_diff);
854853
diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
855854
if (opt->detect_rename && diff_might_be_rename()) {
856855
/* must look at the full tree diff to detect renames */
857856
clear_pathspec(&opt->pathspec);
858-
DIFF_QUEUE_CLEAR(&diff_queued_diff);
857+
diff_queue_clear(&diff_queued_diff);
859858

860859
diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
861860

@@ -1097,7 +1096,7 @@ static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair)
10971096
static void free_diffqueues(int n, struct diff_queue_struct *dq)
10981097
{
10991098
for (int i = 0; i < n; i++)
1100-
diff_free_queue(&dq[i]);
1099+
diff_queue_clear(&dq[i]);
11011100
free(dq);
11021101
}
11031102

@@ -1200,7 +1199,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
12001199
if (parent)
12011200
add_line_range(rev, parent, parent_range);
12021201
free_line_log_data(parent_range);
1203-
diff_free_queue(&queue);
1202+
diff_queue_clear(&queue);
12041203
return changed;
12051204
}
12061205

log-tree.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ static void show_diff_of_diff(struct rev_info *opt)
675675
struct diff_queue_struct dq;
676676

677677
memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
678-
DIFF_QUEUE_CLEAR(&diff_queued_diff);
678+
diff_queue_init(&diff_queued_diff);
679679

680680
fprintf_ln(opt->diffopt.file, "\n%s", opt->idiff_title);
681681
show_interdiff(opt->idiff_oid1, opt->idiff_oid2, 2,
@@ -694,7 +694,7 @@ static void show_diff_of_diff(struct rev_info *opt)
694694
};
695695

696696
memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
697-
DIFF_QUEUE_CLEAR(&diff_queued_diff);
697+
diff_queue_init(&diff_queued_diff);
698698

699699
fprintf_ln(opt->diffopt.file, "\n%s", opt->rdiff_title);
700700
/*

merge-ort.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3536,7 +3536,7 @@ static int detect_and_process_renames(struct merge_options *opt)
35363536
/* Free memory for renames->pairs[] and combined */
35373537
for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) {
35383538
free(renames->pairs[s].queue);
3539-
DIFF_QUEUE_CLEAR(&renames->pairs[s]);
3539+
diff_queue_init(&renames->pairs[s]);
35403540
}
35413541
for (i = 0; i < combined.nr; i++)
35423542
pool_diff_free_filepair(&opt->priv->pool, combined.queue[i]);

0 commit comments

Comments
 (0)