bulk-checkin: fix leaking state TODO
When flushing a bulk-checking to disk we also reset the `struct bulk_checkin_packfile` state. But while we free some of its members, others aren't being free'd, leading to memory leaks: - The temporary packfile name is not getting freed. - The `struct hashfile` only gets freed in case we end up calling `finalize_hashfile()`. There are code paths though where that is not the case, namely when nothing has been written. For this, we need to make `free_hashfile()` public. Fix those leaks. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
9ddd5f755d
commit
c81dcf630c
@ -61,6 +61,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
|
|||||||
|
|
||||||
if (state->nr_written == 0) {
|
if (state->nr_written == 0) {
|
||||||
close(state->f->fd);
|
close(state->f->fd);
|
||||||
|
free_hashfile(state->f);
|
||||||
unlink(state->pack_tmp_name);
|
unlink(state->pack_tmp_name);
|
||||||
goto clear_exit;
|
goto clear_exit;
|
||||||
} else if (state->nr_written == 1) {
|
} else if (state->nr_written == 1) {
|
||||||
@ -83,6 +84,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state)
|
|||||||
free(state->written[i]);
|
free(state->written[i]);
|
||||||
|
|
||||||
clear_exit:
|
clear_exit:
|
||||||
|
free(state->pack_tmp_name);
|
||||||
free(state->written);
|
free(state->written);
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ void hashflush(struct hashfile *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_hashfile(struct hashfile *f)
|
void free_hashfile(struct hashfile *f)
|
||||||
{
|
{
|
||||||
free(f->buffer);
|
free(f->buffer);
|
||||||
free(f->check_buffer);
|
free(f->check_buffer);
|
||||||
|
10
csum-file.h
10
csum-file.h
@ -46,6 +46,16 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *);
|
|||||||
struct hashfile *hashfd(int fd, const char *name);
|
struct hashfile *hashfd(int fd, const char *name);
|
||||||
struct hashfile *hashfd_check(const char *name);
|
struct hashfile *hashfd_check(const char *name);
|
||||||
struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
|
struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the hashfile without flushing its contents to disk. This only
|
||||||
|
* needs to be called when not calling `finalize_hashfile()`.
|
||||||
|
*/
|
||||||
|
void free_hashfile(struct hashfile *f);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finalize the hashfile by flushing data to disk and free'ing it.
|
||||||
|
*/
|
||||||
int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int);
|
int finalize_hashfile(struct hashfile *, unsigned char *, enum fsync_component, unsigned int);
|
||||||
void hashwrite(struct hashfile *, const void *, unsigned int);
|
void hashwrite(struct hashfile *, const void *, unsigned int);
|
||||||
void hashflush(struct hashfile *f);
|
void hashflush(struct hashfile *f);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
test_description='adding and checking out large blobs'
|
test_description='adding and checking out large blobs'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'core.bigFileThreshold must be non-negative' '
|
test_expect_success 'core.bigFileThreshold must be non-negative' '
|
||||||
|
Reference in New Issue
Block a user