ext/zlib/zlib.c in zlib-2.0.0 vs ext/zlib/zlib.c in zlib-2.1.0
- old
+ new
@@ -23,11 +23,11 @@
#else
# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
#endif
-#define RUBY_ZLIB_VERSION "2.0.0"
+#define RUBY_ZLIB_VERSION "2.1.0"
#ifndef RB_PASS_CALLED_KEYWORDS
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
#endif
@@ -352,11 +352,13 @@
/*--- Warning (in finalizer) ---*/
static void
finalizer_warn(const char *msg)
{
+#if 0
fprintf(stderr, "zlib(finalizer): %s\n", msg);
+#endif
}
/*-------- module Zlib --------*/
@@ -544,10 +546,11 @@
struct zstream {
unsigned long flags;
VALUE buf;
VALUE input;
+ VALUE mutex;
z_stream stream;
const struct zstream_funcs {
int (*reset)(z_streamp);
int (*end)(z_streamp);
int (*run)(z_streamp, int);
@@ -619,10 +622,11 @@
zstream_init(struct zstream *z, const struct zstream_funcs *func)
{
z->flags = 0;
z->buf = Qnil;
z->input = Qnil;
+ z->mutex = rb_mutex_new();
z->stream.zalloc = zlib_mem_alloc;
z->stream.zfree = zlib_mem_free;
z->stream.opaque = Z_NULL;
z->stream.msg = Z_NULL;
z->stream.next_in = Z_NULL;
@@ -650,11 +654,13 @@
if (!ZSTREAM_REUSE_BUFFER_P(z)) {
rb_obj_reveal(z->buf, rb_cString);
}
+ rb_mutex_unlock(z->mutex);
rb_protect(rb_yield, z->buf, &state);
+ rb_mutex_lock(z->mutex);
if (ZSTREAM_REUSE_BUFFER_P(z)) {
rb_str_modify(z->buf);
rb_str_set_len(z->buf, 0);
}
@@ -1052,11 +1058,11 @@
args->interrupt = 1;
}
static void
-zstream_run(struct zstream *z, Bytef *src, long len, int flush)
+zstream_run0(struct zstream *z, Bytef *src, long len, int flush)
{
struct zstream_run_args args;
int err;
VALUE old_input = Qnil;
@@ -1093,10 +1099,16 @@
err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)&args,
zstream_unblock_func, (void *)&args,
RB_NOGVL_UBF_ASYNC_SAFE);
#endif
+ /* retry if no exception is thrown */
+ if (err == Z_OK && args.interrupt) {
+ args.interrupt = 0;
+ goto loop;
+ }
+
if (flush != Z_FINISH && err == Z_BUF_ERROR
&& z->stream.avail_out > 0) {
z->flags |= ZSTREAM_FLAG_IN_STREAM;
}
@@ -1130,11 +1142,37 @@
if (args.jump_state)
rb_jump_tag(args.jump_state);
}
+struct zstream_run_synchronized_args {
+ struct zstream *z;
+ Bytef *src;
+ long len;
+ int flush;
+};
+
static VALUE
+zstream_run_synchronized(VALUE value_arg)
+{
+ struct zstream_run_synchronized_args *run_args = (struct zstream_run_synchronized_args *)value_arg;
+ zstream_run0(run_args->z, run_args->src, run_args->len, run_args->flush);
+ return Qnil;
+}
+
+static void
+zstream_run(struct zstream *z, Bytef *src, long len, int flush)
+{
+ struct zstream_run_synchronized_args run_args;
+ run_args.z = z;
+ run_args.src = src;
+ run_args.len = len;
+ run_args.flush = flush;
+ rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&run_args);
+}
+
+static VALUE
zstream_sync(struct zstream *z, Bytef *src, long len)
{
/* VALUE rest; */
int err;
@@ -1175,10 +1213,11 @@
zstream_mark(void *p)
{
struct zstream *z = p;
rb_gc_mark(z->buf);
rb_gc_mark(z->input);
+ rb_gc_mark(z->mutex);
}
static void
zstream_finalize(struct zstream *z)
{
@@ -3512,10 +3551,20 @@
struct gzfile *gz;
TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
return gz->path;
}
+static VALUE
+gzfile_initialize_path_partial(VALUE obj)
+{
+ struct gzfile* gz;
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
+ gz->path = rb_funcall(gz->io, id_path, 0);
+ rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
+ return Qnil;
+}
+
static void
rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
{
if (!NIL_P(opts)) {
rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2, NULL);
@@ -3620,12 +3669,12 @@
gz->io = io;
ZSTREAM_READY(&gz->z);
rb_gzfile_ecopts(gz, opt);
if (rb_respond_to(io, id_path)) {
- gz->path = rb_funcall(gz->io, id_path, 0);
- rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
+ /* File#path may raise IOError in case when a path is unavailable */
+ rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
}
return obj;
}
@@ -3882,12 +3931,12 @@
ZSTREAM_READY(&gz->z);
gzfile_read_header(gz, Qnil);
rb_gzfile_ecopts(gz, opt);
if (rb_respond_to(io, id_path)) {
- gz->path = rb_funcall(gz->io, id_path, 0);
- rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
+ /* File#path may raise IOError in case when a path is unavailable */
+ rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
}
return obj;
}
@@ -4546,10 +4595,10 @@
#endif /* GZIP_SUPPORT */
void
Init_zlib(void)
{
-#if HAVE_RB_EXT_RACTOR_SAFE
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
rb_ext_ractor_safe(true);
#endif
#undef rb_intern
VALUE mZlib, cZStream, cDeflate, cInflate;