Skip to content

Commit 99c6c62

Browse files
committed
Don't call rb_str_set_len while released the GVL.
1 parent bce161f commit 99c6c62

File tree

1 file changed

+67
-62
lines changed

1 file changed

+67
-62
lines changed

ext/zlib/zlib.c

+67-62
Original file line numberDiff line numberDiff line change
@@ -720,17 +720,15 @@ zstream_expand_buffer_into(struct zstream *z, unsigned long size)
720720
}
721721
}
722722

723-
static void *
724-
zstream_expand_buffer_protect(void *ptr)
723+
static int
724+
zstream_expand_buffer_protect(struct zstream *z)
725725
{
726-
struct zstream *z = (struct zstream *)ptr;
727726
int state = 0;
728727

729728
rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
730729

731-
return (void *)(VALUE)state;
730+
return state;
732731
}
733-
734732
static int
735733
zstream_expand_buffer_non_stream(struct zstream *z)
736734
{
@@ -1023,57 +1021,14 @@ zstream_ensure_end(VALUE v)
10231021
}
10241022

10251023
static void *
1026-
zstream_run_func(void *ptr)
1024+
zstream_run_once(void *_arguments)
10271025
{
1028-
struct zstream_run_args *args = (struct zstream_run_args *)ptr;
1029-
int err, state, flush = args->flush;
1030-
struct zstream *z = args->z;
1031-
uInt n;
1032-
1033-
err = Z_OK;
1034-
while (!args->interrupt) {
1035-
n = z->stream.avail_out;
1036-
err = z->func->run(&z->stream, flush);
1037-
rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
1038-
1039-
if (err == Z_STREAM_END) {
1040-
z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
1041-
z->flags |= ZSTREAM_FLAG_FINISHED;
1042-
break;
1043-
}
1044-
1045-
if (err != Z_OK && err != Z_BUF_ERROR)
1046-
break;
1047-
1048-
if (z->stream.avail_out > 0) {
1049-
z->flags |= ZSTREAM_FLAG_IN_STREAM;
1050-
break;
1051-
}
1052-
1053-
if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
1054-
/* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
1055-
/* but deflate() could be called with avail_in == 0 (there's hidden buffer
1056-
in zstream->state) */
1057-
z->flags |= ZSTREAM_FLAG_IN_STREAM;
1058-
break;
1059-
}
1026+
struct zstream_run_args *arguments = (struct zstream_run_args *)_arguments;
1027+
struct zstream *z = arguments->z;
10601028

1061-
if (args->stream_output) {
1062-
state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
1063-
(void *)z);
1064-
}
1065-
else {
1066-
state = zstream_expand_buffer_non_stream(z);
1067-
}
1029+
uintptr_t error = z->func->run(&z->stream, arguments->flush);
10681030

1069-
if (state) {
1070-
err = Z_OK; /* buffer expanded but stream processing was stopped */
1071-
args->jump_state = state;
1072-
break;
1073-
}
1074-
}
1075-
1076-
return (void *)(VALUE)err;
1031+
return (void*)error;
10771032
}
10781033

10791034
/*
@@ -1088,6 +1043,64 @@ zstream_unblock_func(void *ptr)
10881043
args->interrupt = 1;
10891044
}
10901045

1046+
static int
1047+
zstream_run_func(struct zstream_run_args *args)
1048+
{
1049+
struct zstream *z = args->z;
1050+
int state;
1051+
uInt n;
1052+
1053+
int err = Z_OK;
1054+
while (!args->interrupt) {
1055+
n = z->stream.avail_out;
1056+
1057+
#ifndef RB_NOGVL_UBF_ASYNC_SAFE
1058+
err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_once, (void *)args, zstream_unblock_func, (void *)args);
1059+
#else
1060+
err = (int)(VALUE)rb_nogvl(zstream_run_once, (void *)args, zstream_unblock_func, (void *)args, RB_NOGVL_UBF_ASYNC_SAFE);
1061+
#endif
1062+
1063+
rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
1064+
1065+
if (err == Z_STREAM_END) {
1066+
z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
1067+
z->flags |= ZSTREAM_FLAG_FINISHED;
1068+
break;
1069+
}
1070+
1071+
if (err != Z_OK && err != Z_BUF_ERROR)
1072+
break;
1073+
1074+
if (z->stream.avail_out > 0) {
1075+
z->flags |= ZSTREAM_FLAG_IN_STREAM;
1076+
break;
1077+
}
1078+
1079+
if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
1080+
/* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
1081+
/* but deflate() could be called with avail_in == 0 (there's hidden buffer
1082+
in zstream->state) */
1083+
z->flags |= ZSTREAM_FLAG_IN_STREAM;
1084+
break;
1085+
}
1086+
1087+
if (args->stream_output) {
1088+
state = zstream_expand_buffer_protect(z);
1089+
}
1090+
else {
1091+
state = zstream_expand_buffer_non_stream(z);
1092+
}
1093+
1094+
if (state) {
1095+
err = Z_OK; /* buffer expanded but stream processing was stopped */
1096+
args->jump_state = state;
1097+
break;
1098+
}
1099+
}
1100+
1101+
return err;
1102+
}
1103+
10911104
static VALUE
10921105
zstream_run_try(VALUE value_arg)
10931106
{
@@ -1096,7 +1109,6 @@ zstream_run_try(VALUE value_arg)
10961109
Bytef *src = args->src;
10971110
long len = args->len;
10981111
int flush = args->flush;
1099-
11001112
int err;
11011113
VALUE old_input = Qnil;
11021114

@@ -1126,14 +1138,7 @@ zstream_run_try(VALUE value_arg)
11261138
}
11271139

11281140
loop:
1129-
#ifndef RB_NOGVL_UBF_ASYNC_SAFE
1130-
err = (int)(VALUE)rb_thread_call_without_gvl(zstream_run_func, (void *)args,
1131-
zstream_unblock_func, (void *)args);
1132-
#else
1133-
err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args,
1134-
zstream_unblock_func, (void *)args,
1135-
RB_NOGVL_UBF_ASYNC_SAFE);
1136-
#endif
1141+
err = zstream_run_func(args);
11371142

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

0 commit comments

Comments
 (0)