Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly return thread interrupt state in zstream_run_func #74

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
os: windows-latest
- ruby: truffleruby-head
os: windows-latest
- ruby: truffleruby-head
os: macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand Down
10 changes: 8 additions & 2 deletions ext/zlib/zlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ struct zstream {
#define ZSTREAM_REUSE_BUFFER_P(z) ((z)->flags & ZSTREAM_REUSE_BUFFER)

#define ZSTREAM_EXPAND_BUFFER_OK 0
#define ZSTREAM_THREAD_INTERRUPTED 9

/* I think that more better value should be found,
but I gave up finding it. B) */
Expand Down Expand Up @@ -1019,7 +1020,7 @@ zstream_run_func(void *ptr)
uInt n;

err = Z_OK;
while (!args->interrupt) {
while (1) {
n = z->stream.avail_out;
err = z->func->run(&z->stream, flush);
rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
Expand Down Expand Up @@ -1059,6 +1060,11 @@ zstream_run_func(void *ptr)
args->jump_state = state;
break;
}

if (args->interrupt) {
err = ZSTREAM_THREAD_INTERRUPTED;
break;
}
}

return (void *)(VALUE)err;
Expand Down Expand Up @@ -1118,7 +1124,7 @@ zstream_run_try(VALUE value_arg)
#endif

/* retry if no exception is thrown */
if (err == Z_OK && args->interrupt) {
if (err == ZSTREAM_THREAD_INTERRUPTED) {
args->interrupt = 0;
goto loop;
}
Expand Down
37 changes: 37 additions & 0 deletions test/zlib/test_zlib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1473,5 +1473,42 @@ def test_gunzip_no_memory_leak
10_000.times {Zlib.gunzip(d)}
};
end

def test_gzip_thread_interrupts
content = SecureRandom.random_bytes(5000)
stop = false
ret = nil

thr = Thread.new do
until stop
ret = Zlib.gzip(content)
end
end

10000000.times { thr.wakeup }
stop = true
thr.join

assert_equal content, Zlib.gunzip(ret)
end

def test_gzipreader_thread_interrupts
content = SecureRandom.random_bytes(5000)
gzipped = Zlib.gzip(content)
stop = false
ret = nil

thr = Thread.new do
until stop
ret = Zlib::GzipReader.new(StringIO.new(gzipped), encoding: Encoding::BINARY).read
end
end

10000000.times { thr.wakeup }
stop = true
thr.join

assert_equal content, ret
end
end
end
Loading