/* if we already have max_buffer_size amount of data, fail here */
if (stream->pos - stream->skip >= i_stream_get_max_buffer_size(&stream->istream))
return -2;
+ if (i_stream_get_data_size(zstream->istream.parent) > 0) {
+ /* Parent stream was only partially consumed. Set the stream's
+ IO as pending to avoid hangs. */
+ i_stream_set_input_pending(&zstream->istream.istream, TRUE);
+ }
/* allocate enough space for the old data and the new
decompressed chunk. we don't know the original compressed size,
so just allocate the max amount of memory. */
out_size -= zstream->strm.avail_out;
stream->pos += out_size;
- i_stream_skip(stream->parent, size - zstream->strm.avail_in);
+ size_t bytes_consumed = size - zstream->strm.avail_in;
+ i_stream_skip(stream->parent, bytes_consumed);
+ if (i_stream_get_data_size(stream->parent) > 0 &&
+ (bytes_consumed > 0 || out_size > 0)) {
+ /* Parent stream was only partially consumed. Set the stream's
+ IO as pending to avoid hangs. */
+ i_stream_set_input_pending(&stream->istream, TRUE);
+ }
if (lzma_handle_error(zstream, ret) < 0) {
return -1;
out_size);
stream->pos += out_size;
- i_stream_skip(stream->parent, size - zstream->zs.avail_in);
+ size_t bytes_consumed = size - zstream->zs.avail_in;
+ i_stream_skip(stream->parent, bytes_consumed);
+ if (i_stream_get_data_size(stream->parent) > 0 &&
+ (bytes_consumed > 0 || out_size > 0)) {
+ /* Parent stream was only partially consumed. Set the stream's
+ IO as pending to avoid hangs. */
+ i_stream_set_input_pending(&stream->istream, TRUE);
+ }
switch (ret) {
case Z_OK:
if (ret == 0)
return 0;
buffer_append(zstream->frame_buffer, data, size);
+ /* NOTE: All of the parent stream input is skipped
+ over here. This is why there's no need to call
+ i_stream_set_input_pending() here like with other
+ compression istreams. */
i_stream_skip(stream->parent, size);
zstream->input.src = zstream->frame_buffer->data;
zstream->input.size = zstream->frame_buffer->used;