Create a linked list to safely release data which cannot be released earlier after all compression is complete and all compressionthreads have returned, fixing a minor leak.

This commit is contained in:
Con Kolivas 2021-02-09 18:05:49 +11:00
parent 9f544dc372
commit 96c7c62584
3 changed files with 40 additions and 39 deletions

View file

@ -351,8 +351,15 @@ struct checksum {
typedef i64 tag;
struct node {
void *data;
struct node *prev;
};
struct rzip_state {
void *ss;
struct node *sslist;
struct node *head;
struct level *level;
tag hash_index[256];
struct hash_entry *hash_table;
@ -444,10 +451,6 @@ struct rzip_control {
const char *util_infile;
char delete_infile;
const char *util_outfile;
#define STREAM_BUCKET_SIZE 20
size_t sinfo_buckets;
size_t sinfo_idx;
struct stream_info **sinfo_queue;
char delete_outfile;
FILE *outputfile;
char library_mode;

35
rzip.c
View file

@ -872,6 +872,17 @@ init_sliding_mmap(rzip_control *control, struct rzip_state *st, int fd_in,
sb->fd = fd_in;
}
static void add_to_sslist(rzip_control *control, struct rzip_state *st)
{
struct node *node = calloc(sizeof(struct node), 1);
if (unlikely(!node))
failure("Failed to calloc struct node in add_to_sslist\n");
node->data = st->ss;
node->prev = st->sslist;
st->head = node;
}
/* compress a chunk of an open file. Assumes that the file is able to
be mmap'd and is seekable */
static inline void
@ -903,6 +914,23 @@ rzip_chunk(rzip_control *control, struct rzip_state *st, int fd_in, int fd_out,
if (unlikely(close_stream_out(control, st->ss)))
failure("Failed to flush/close streams in rzip_chunk\n");
/* Save the sinfo data to a list to be safely released after all
* threads have been shut down. */
add_to_sslist(control, st);
}
static void clear_sslist(struct rzip_state *st)
{
while (st->head) {
struct node *node = st->head;
struct stream_info *sinfo = node->data;
dealloc(sinfo->s);
dealloc(sinfo);
st->head = node->prev;
dealloc(node);
}
}
/* compress a whole file chunks at a time */
@ -1225,12 +1253,12 @@ retry:
print_progress("Compression Ratio: %.3f. Average Compression Speed: %6.3fMB/s.\n",
1.0 * s.st_size / s2.st_size, chunkmbs);
clear_sslist(st);
dealloc(st);
}
void rzip_control_free(rzip_control *control)
{
size_t x;
if (!control)
return;
@ -1240,10 +1268,5 @@ void rzip_control_free(rzip_control *control)
if (control->suffix && control->suffix[0])
dealloc(control->suffix);
for (x = 0; x < control->sinfo_idx; x++) {
dealloc(control->sinfo_queue[x]->s);
dealloc(control->sinfo_queue[x]);
}
dealloc(control->sinfo_queue);
dealloc(control);
}

View file

@ -1812,37 +1812,12 @@ int close_stream_out(rzip_control *control, void *ss)
for (i = 0; i < sinfo->num_streams; i++)
rewrite_encrypted(control, sinfo, sinfo->s[i].last_headofs);
}
if (control->library_mode) {
if (!control->sinfo_buckets) {
/* no streams added */
control->sinfo_queue = calloc(STREAM_BUCKET_SIZE + 1, sizeof(void*));
if (!control->sinfo_queue) {
print_err("Failed to calloc sinfo_queue in close_stream_out\n");
return -1;
}
control->sinfo_buckets++;
} else if (control->sinfo_idx == STREAM_BUCKET_SIZE * control->sinfo_buckets + 1) {
/* all buckets full, create new bucket */
void *tmp;
tmp = realloc(control->sinfo_queue, (++control->sinfo_buckets * STREAM_BUCKET_SIZE + 1) * sizeof(void*));
if (!tmp) {
print_err("Failed to realloc sinfo_queue in close_stream_out\n");
return -1;
}
control->sinfo_queue = tmp;
memset(control->sinfo_queue + control->sinfo_idx, 0, ((control->sinfo_buckets * STREAM_BUCKET_SIZE + 1) - control->sinfo_idx) * sizeof(void*));
}
control->sinfo_queue[control->sinfo_idx++] = sinfo;
}
#if 0
/* These cannot be freed immediately because their values are read after the next
* stream has started. Instead (in library mode), they are stored and only freed
* after the entire operation has completed.
/* Note that sinfo->s and sinfo are not released here but after compression
* has completed as they cannot be freed immediately because their values
* are read after the next stream has started.
*/
dealloc(sinfo->s);
dealloc(sinfo);
#endif
return 0;
}