aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2022-10-24 16:25:09 +0300
committerLasse Collin <lasse.collin@tukaani.org>2022-10-24 16:25:09 +0300
commitfda9f85f52c546f7ca0313cf89481da4707fecb3 (patch)
tree0f0fea3a5a10a309ccb50b56795b66eedec971e2 /src/liblzma/common
parenttuklib_cpucores: Use HW_NCPUONLINE on OpenBSD. (diff)
downloadxz-fda9f85f52c546f7ca0313cf89481da4707fecb3.tar.xz
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.
Diffstat (limited to 'src/liblzma/common')
-rw-r--r--src/liblzma/common/stream_decoder_mt.c33
1 files changed, 26 insertions, 7 deletions
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.