From fda9f85f52c546f7ca0313cf89481da4707fecb3 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 24 Oct 2022 16:25:09 +0300 Subject: liblzma: Threaded decoder: Stop the worker threads on errors. It's waste of CPU time and electricity to leave the unfinished worker threads running when it is known that their output will get ignored. --- src/liblzma/common/stream_decoder_mt.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/liblzma/common/stream_decoder_mt.c b/src/liblzma/common/stream_decoder_mt.c index 840051b0..295f913d 100644 --- a/src/liblzma/common/stream_decoder_mt.c +++ b/src/liblzma/common/stream_decoder_mt.c @@ -1169,9 +1169,16 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator, // The downside of this is that with fail-fast apps // cannot always distinguish between corrupt and // truncated files. - if (action == LZMA_FINISH && coder->fail_fast) + if (action == LZMA_FINISH && coder->fail_fast) { + // We won't produce any more output. Stop + // the unfinished worker threads so they + // won't waste CPU time. + threads_stop(coder); return LZMA_DATA_ERROR; + } + // read_output_and_wait() will call threads_stop() + // if needed so with that we can use return_if_error. return_if_error(read_output_and_wait(coder, allocator, out, out_pos, out_size, NULL, waiting_allowed, @@ -1447,12 +1454,20 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator, } // Allocate memory for the output buffer in the output queue. - return_if_error(lzma_outq_prealloc_buf( + lzma_ret ret = lzma_outq_prealloc_buf( &coder->outq, allocator, - coder->block_options.uncompressed_size)); + coder->block_options.uncompressed_size); + if (ret != LZMA_OK) { + threads_stop(coder); + return ret; + } // Set up coder->thr. - return_if_error(get_thread(coder, allocator)); + ret = get_thread(coder, allocator); + if (ret != LZMA_OK) { + threads_stop(coder); + return ret; + } // The new Block decoder memory usage is already counted in // coder->mem_in_use. Store it in the thread too. @@ -1460,7 +1475,7 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator, // Initialize the Block decoder. coder->thr->block_options = coder->block_options; - const lzma_ret ret = lzma_block_decoder_init( + ret = lzma_block_decoder_init( &coder->thr->block_decoder, allocator, &coder->thr->block_options); @@ -1480,8 +1495,10 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator, // Allocate the input buffer. coder->thr->in_size = coder->mem_next_in; coder->thr->in = lzma_alloc(coder->thr->in_size, allocator); - if (coder->thr->in == NULL) + if (coder->thr->in == NULL) { + threads_stop(coder); return LZMA_MEM_ERROR; + } // Get the preallocated output buffer. coder->thr->outbuf = lzma_outq_get_buf( @@ -1516,8 +1533,10 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator, const size_t in_avail = in_size - *in_pos; const size_t in_needed = coder->thr->in_size - coder->thr->in_filled; - if (in_avail < in_needed) + if (in_avail < in_needed) { + threads_stop(coder); return LZMA_DATA_ERROR; + } } // Copy input to the worker thread. -- cgit v1.2.3