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.
This commit is contained in:
Lasse Collin 2022-10-24 16:25:09 +03:00
parent 2611c4d905
commit fda9f85f52
1 changed files with 26 additions and 7 deletions

View File

@ -1169,9 +1169,16 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator,
// The downside of this is that with fail-fast apps // The downside of this is that with fail-fast apps
// cannot always distinguish between corrupt and // cannot always distinguish between corrupt and
// truncated files. // 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; 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, return_if_error(read_output_and_wait(coder, allocator,
out, out_pos, out_size, out, out_pos, out_size,
NULL, waiting_allowed, 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. // 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->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. // 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 // The new Block decoder memory usage is already counted in
// coder->mem_in_use. Store it in the thread too. // 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. // Initialize the Block decoder.
coder->thr->block_options = coder->block_options; 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_decoder, allocator,
&coder->thr->block_options); &coder->thr->block_options);
@ -1480,8 +1495,10 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator,
// Allocate the input buffer. // Allocate the input buffer.
coder->thr->in_size = coder->mem_next_in; coder->thr->in_size = coder->mem_next_in;
coder->thr->in = lzma_alloc(coder->thr->in_size, allocator); 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; return LZMA_MEM_ERROR;
}
// Get the preallocated output buffer. // Get the preallocated output buffer.
coder->thr->outbuf = lzma_outq_get_buf( 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_avail = in_size - *in_pos;
const size_t in_needed = coder->thr->in_size const size_t in_needed = coder->thr->in_size
- coder->thr->in_filled; - coder->thr->in_filled;
if (in_avail < in_needed) if (in_avail < in_needed) {
threads_stop(coder);
return LZMA_DATA_ERROR; return LZMA_DATA_ERROR;
}
} }
// Copy input to the worker thread. // Copy input to the worker thread.