Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions ext/zlib/zlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ zstream_run_func(struct zstream_run_args *args)
uInt n;

int err = Z_OK;
while (!args->interrupt) {
while (1) {
n = z->stream.avail_out;

err = (int)(VALUE)rb_ensure(zstream_run_once_begin, (VALUE)args, zstream_run_once_ensure, (VALUE)args);
Expand Down Expand Up @@ -1167,18 +1167,6 @@ zstream_run_try(VALUE value_arg)
loop:
err = zstream_run_func(args);

/* retry if no exception is thrown */
if (err == Z_OK && args->interrupt) {
args->interrupt = 0;

/* Retry only if both avail_in > 0 (more input to process) and avail_out > 0
* (output buffer has space). If avail_out == 0, the buffer is full and should
* be consumed by the caller first. If avail_in == 0, there's nothing more to process. */
if (z->stream.avail_in > 0 && z->stream.avail_out > 0) {
goto loop;
}
}

if (flush != Z_FINISH && err == Z_BUF_ERROR && z->stream.avail_out > 0) {
z->flags |= ZSTREAM_FLAG_IN_STREAM;
}
Expand Down
31 changes: 31 additions & 0 deletions test/zlib/test_zlib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,37 @@ def test_close
assert_raise(Zlib::Error) { z << "foo" }
assert_raise(Zlib::Error) { z.reset }
end

# An interrupt must neither raise Zlib::BufError on a deflate call that
# already consumed all its input, nor stop Zlib::Deflate#finish before the
# stream ends.
def test_thread_wakeup_interrupt
pend 'fails' if RUBY_ENGINE == 'truffleruby'

content = SecureRandom.random_bytes(256 * 1024)
outputs = []

thr = Thread.new do
100.times do
z = Zlib::Deflate.new
outputs << (z.deflate(content) << z.finish)
z.close
end
end

while thr.alive?
begin
thr.wakeup
rescue ThreadError
end
Thread.pass
end
thr.join

outputs.each do |output|
assert_equal(content, Zlib::Inflate.inflate(output))
end
end
end

class TestZlibInflate < Test::Unit::TestCase
Expand Down
Loading