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;