From: "H.Yamamoto" Date: 2006-02-07T16:01:05+09:00 Subject: [ruby-dev:28310] Re: SEGV with zlib 山本です。 >パッチを作るならこんな感じでしょうか。ついでに大量のwarnigを >消しています。本質は「#if 0」のところだけ。 zstream_run でも ruby オブジェクトに触るようなので、本当に警告 だけにするならこんな感じでしょうか。厳密には rb_warn も $stderr に 触るはずですが・・・・(以前 ruby/tk 絡みで、それに関係した SEGV を 見たような) Index: zlib.c =================================================================== RCS file: /src/ruby/ext/zlib/zlib.c,v retrieving revision 1.29 diff -u -w -b -p -r1.29 zlib.c --- zlib.c 14 Dec 2005 16:37:24 -0000 1.29 +++ zlib.c 7 Feb 2006 06:56:26 -0000 @@ -127,7 +127,6 @@ static void gzfile_calc_crc _((struct gz static VALUE gzfile_read _((struct gzfile*, int)); static VALUE gzfile_read_all _((struct gzfile*)); static void gzfile_ungetc _((struct gzfile*, int)); -static VALUE gzfile_finalize _((VALUE)); static void gzfile_writer_end _((struct gzfile*)); static void gzfile_reader_end _((struct gzfile*)); static void gzfile_reader_rewind _((struct gzfile*)); @@ -365,14 +364,12 @@ struct zstream { #define ZSTREAM_FLAG_READY 0x1 #define ZSTREAM_FLAG_IN_STREAM 0x2 #define ZSTREAM_FLAG_FINISHED 0x4 -#define ZSTREAM_FLAG_FINALIZE 0x8 #define ZSTREAM_FLAG_CLOSED 0x10 #define ZSTREAM_FLAG_UNUSED 0x20 #define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY) #define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY) #define ZSTREAM_IS_FINISHED(z) ((z)->flags & ZSTREAM_FLAG_FINISHED) -#define ZSTREAM_IS_FINALIZE(z) ((z)->flags & ZSTREAM_FLAG_FINALIZE) #define ZSTREAM_IS_CLOSED(z) ((z)->flags & ZSTREAM_FLAG_CLOSED) /* I think that more better value should be found, @@ -661,7 +658,7 @@ zstream_reset(z) int err; err = z->func->reset(&z->stream); - if (err != Z_OK && !ZSTREAM_IS_FINALIZE(z)) { + if (err != Z_OK) { raise_zlib_error(err, z->stream.msg); } z->flags = ZSTREAM_FLAG_READY; @@ -678,7 +675,7 @@ zstream_end(z) { int err; - if (!ZSTREAM_IS_READY(z) && !ZSTREAM_IS_FINALIZE(z)) { + if (!ZSTREAM_IS_READY(z)) { if (RTEST(ruby_debug)) { rb_warning("attempt to close uninitialized zstream; ignored."); } @@ -693,7 +690,7 @@ zstream_end(z) zstream_reset_input(z); err = z->func->end(&z->stream); - if (err != Z_OK && !ZSTREAM_IS_FINALIZE(z)) { + if (err != Z_OK) { raise_zlib_error(err, z->stream.msg); } z->flags = 0; @@ -820,8 +817,9 @@ static void zstream_free(z) struct zstream *z; { - z->flags |= ZSTREAM_FLAG_FINALIZE; - zstream_end(z); + if (ZSTREAM_IS_READY(z) && !ZSTREAM_IS_CLOSED(z)) { + rb_warning("zstream must be closed explicitly."); + } free(z); } @@ -1750,9 +1748,11 @@ static void gzfile_free(gz) struct gzfile *gz; { - gz->z.flags |= ZSTREAM_FLAG_FINALIZE; - if (ZSTREAM_IS_READY(&gz->z)) { - gz->end(gz); + if (ZSTREAM_IS_READY(&gz->z) && !ZSTREAM_IS_CLOSED(&gz->z)) { + if (gz->end == gzfile_reader_end) + rb_warn("Zlib::GzipReader object must be closed explicitly."); + if (gz->end == gzfile_writer_end) + rb_warn("Zlib::GzipWriter object must be closed explicitly."); } free(gz); } @@ -2256,21 +2256,10 @@ gzfile_ungetc(gz, c) gz->ungetc++; } -static VALUE -gzfile_finalize(obj) - VALUE obj; -{ - struct gzfile *gz = (struct gzfile *)obj; - gzfile_write_raw(gz); - return Qnil; -} - static void gzfile_writer_end(gz) struct gzfile *gz; { - int aborted; - if (ZSTREAM_IS_CLOSED(&gz->z)) return; gz->z.flags |= ZSTREAM_FLAG_CLOSED; @@ -2280,22 +2269,6 @@ gzfile_writer_end(gz) zstream_run(&gz->z, "", 0, Z_FINISH); gzfile_make_footer(gz); - - if (ZSTREAM_IS_FINALIZE(&gz->z)) { - if (NIL_P(gz->io)) return; - rb_warn("Zlib::GzipWriter object must be closed explicitly."); - if (!SPECIAL_CONST_P(gz->io) && OBJ_IS_FREED(gz->io)) { - aborted = 1; - } - else { - rb_protect(gzfile_finalize, (VALUE)gz, &aborted); - } - if (aborted) { - rb_warn("gzip footer is not written; broken gzip file"); - } - zstream_end(&gz->z); - return; - } gzfile_write_raw(gz); zstream_end(&gz->z); } @@ -2308,7 +2281,6 @@ gzfile_reader_end(gz) gz->z.flags |= ZSTREAM_FLAG_CLOSED; if (GZFILE_IS_FINISHED(gz) - && !ZSTREAM_IS_FINALIZE(&gz->z) && !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { gzfile_check_footer(gz); }