aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2022-04-06 12:39:49 +0300
committerLasse Collin <lasse.collin@tukaani.org>2022-04-06 13:16:00 +0300
commit90621da7f6e1bfd6d91d60415eae04b2bca274c2 (patch)
tree94a29abbb0dd5d7a7a9646ac8390aff8c9c6f711 /src/liblzma/common
parentliblzma: Threaded decoder: Always wait for output if LZMA_FINISH is used. (diff)
downloadxz-90621da7f6e1bfd6d91d60415eae04b2bca274c2.tar.xz
liblzma: Add a new flag LZMA_FAIL_FAST for threaded decoder.
In most cases if the input file is corrupt the application won't care about the uncompressed content at all. With this new flag the threaded decoder will return an error as soon as any thread has detected an error; it won't wait to copy out the data before the location of the error. I don't plan to use this in xz to keep the behavior consistent between single-threaded and multi-threaded modes.
Diffstat (limited to 'src/liblzma/common')
-rw-r--r--src/liblzma/common/common.h7
-rw-r--r--src/liblzma/common/stream_decoder_mt.c50
2 files changed, 32 insertions, 25 deletions
diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h
index 67996228..36366dbc 100644
--- a/src/liblzma/common/common.h
+++ b/src/liblzma/common/common.h
@@ -67,14 +67,15 @@
#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
-/// Supported flags that can be passed to lzma_stream_decoder()
-/// or lzma_auto_decoder().
+/// Supported flags that can be passed to lzma_stream_decoder(),
+/// lzma_auto_decoder(), or lzma_stream_decoder_mt().
#define LZMA_SUPPORTED_FLAGS \
( LZMA_TELL_NO_CHECK \
| LZMA_TELL_UNSUPPORTED_CHECK \
| LZMA_TELL_ANY_CHECK \
| LZMA_IGNORE_CHECK \
- | LZMA_CONCATENATED )
+ | LZMA_CONCATENATED \
+ | LZMA_FAIL_FAST )
/// Largest valid lzma_action value as unsigned integer.
diff --git a/src/liblzma/common/stream_decoder_mt.c b/src/liblzma/common/stream_decoder_mt.c
index 7f445982..32e0b892 100644
--- a/src/liblzma/common/stream_decoder_mt.c
+++ b/src/liblzma/common/stream_decoder_mt.c
@@ -300,6 +300,10 @@ struct lzma_stream_coder {
/// Stream Padding is a multiple of four bytes.
bool concatenated;
+ /// If true, we will return any errors immediately instead of first
+ /// producing all output before the location of the error.
+ bool fail_fast;
+
/// When decoding concatenated Streams, this is true as long as we
/// are decoding the first Stream. This is needed to avoid misleading
@@ -711,13 +715,12 @@ read_output_and_wait(struct lzma_stream_coder *coder,
coder->pending_error
= coder->thread_error;
- // FIXME? Add a flag to do this conditionally?
- // That way errors would get reported to the
- // application without a delay.
-// if (coder->fast_errors) {
-// ret = coder->thread_error;
-// break;
-// }
+ // If LZMA_FAIL_FAST was used, report errors
+ // from worker threads immediately.
+ if (coder->fail_fast) {
+ ret = coder->thread_error;
+ break;
+ }
}
// Check if decoding of the next Block can be started.
@@ -1690,22 +1693,24 @@ stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator,
break;
case SEQ_ERROR:
- // Let the application get all data before the point where
- // the error was detected. This matches the behavior of
- // single-threaded use.
- //
- // FIXME? Some errors (LZMA_MEM_ERROR) don't get here,
- // they are returned immediately. Thus in rare cases the
- // output will be less than in single-threaded mode. But
- // maybe this doesn't matter much in practice.
- return_if_error(read_output_and_wait(coder, allocator,
- out, out_pos, out_size,
- NULL, true, &wait_abs, &has_blocked));
+ if (!coder->fail_fast) {
+ // Let the application get all data before the point
+ // where the error was detected. This matches the
+ // behavior of single-threaded use.
+ //
+ // FIXME? Some errors (LZMA_MEM_ERROR) don't get here,
+ // they are returned immediately. Thus in rare cases
+ // the output will be less than in the single-threaded
+ // mode. Maybe this doesn't matter much in practice.
+ return_if_error(read_output_and_wait(coder, allocator,
+ out, out_pos, out_size,
+ NULL, true, &wait_abs, &has_blocked));
- // We get here only if the error happened in the main thread,
- // for example, unsupported Block Header.
- if (!lzma_outq_is_empty(&coder->outq))
- return LZMA_OK;
+ // We get here only if the error happened in the main
+ // thread, for example, unsupported Block Header.
+ if (!lzma_outq_is_empty(&coder->outq))
+ return LZMA_OK;
+ }
return coder->pending_error;
@@ -1900,6 +1905,7 @@ stream_decoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator,
coder->tell_any_check = (options->flags & LZMA_TELL_ANY_CHECK) != 0;
coder->ignore_check = (options->flags & LZMA_IGNORE_CHECK) != 0;
coder->concatenated = (options->flags & LZMA_CONCATENATED) != 0;
+ coder->fail_fast = (options->flags & LZMA_FAIL_FAST) != 0;
coder->first_stream = true;
coder->out_was_filled = false;