diff --git a/lrzip.c b/lrzip.c index ac3c923..16e7948 100644 --- a/lrzip.c +++ b/lrzip.c @@ -782,6 +782,12 @@ static void release_hashes(rzip_control *control) static void clear_rulist(rzip_control *control) { + /* If we're unable to safely clean up thread-related memory due to + * a failure in decompression, let the small memory leak be cleaned + * up by process exit */ + if (unlikely(control->thread_count > 0)) { + return; + } while (control->ruhead) { struct runzip_node *node = control->ruhead; struct stream_info *sinfo = node->sinfo; diff --git a/lrzip_private.h b/lrzip_private.h index 622ffee..d2ce1eb 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef HAVE_PTHREAD_H # include @@ -467,6 +468,7 @@ struct rzip_control { pthread_t *pthreads; struct runzip_node *ruhead; + atomic_int thread_count; }; struct uncomp_thread { diff --git a/stream.c b/stream.c index bc5b207..88602ff 100644 --- a/stream.c +++ b/stream.c @@ -56,6 +56,7 @@ #endif #include +#include /* LZMA C Wrapper */ #include "lzma/C/LzmaLib.h" @@ -124,8 +125,11 @@ static bool cond_broadcast(rzip_control *control, pthread_cond_t *cond) bool create_pthread(rzip_control *control, pthread_t *thread, pthread_attr_t * attr, void * (*start_routine)(void *), void *arg) { - if (unlikely(pthread_create(thread, attr, start_routine, arg))) + atomic_fetch_add(&control->thread_count, 1); + if (unlikely(pthread_create(thread, attr, start_routine, arg))) { + atomic_fetch_sub(&control->thread_count, 1); fatal_return(("Failed to pthread_create\n"), false); + } return true; } @@ -140,6 +144,7 @@ bool join_pthread(rzip_control *control, pthread_t th, void **thread_return) { if (pthread_join(th, thread_return)) fatal_return(("Failed to pthread_join\n"), false); + atomic_fetch_sub(&control->thread_count, 1); return true; }