]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
liblzma: Threaded decoder: Stop the worker threads on errors.
authorLasse Collin <lasse.collin@tukaani.org>
Mon, 24 Oct 2022 13:25:09 +0000 (16:25 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Mon, 24 Oct 2022 13:25:09 +0000 (16:25 +0300)
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

index 840051b0f7f7e2ae49a3de0e5ad3c40416c55620..295f913dca40c18071aa22dec41707a0270fb574 100644 (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
                        // 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.