[#28337] constant look up order in CVS HEAD — Yukihiro Matsumoto <matz@...>

まつもと ゆきひろです

15 messages 2006/02/18
[#28338] Re: constant look up order in CVS HEAD — Tanaka Akira <akr@...17n.org> 2006/02/19

In article <1140229116.805371.31930.nullmailer@x31.priv.netlab.jp>,

[#28341] Re: constant look up order in CVS HEAD — GOTOU Yuuzou <gotoyuzo@...> 2006/02/19

In message <87lkw8xfay.fsf@m17n.org>,

[#28342] Re: constant look up order in CVS HEAD — Yukihiro Matsumoto <matz@...> 2006/02/19

まつもと ゆきひろです

[ruby-dev:28324] Re: SEGV with zlib

From: "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
Date: 2006-02-09 01:22:43 UTC
List: ruby-dev #28324
山本です。

>|コミットしておきました。ZSTREAM_FLAG_CLOSED は必要ないと思ったんですが
>|こんなことをすると落ちるので必要なんですね。うーむ。
>
>書き込みを行っていないZlib::GzipWriterをcloseしない場合でも
>警告が出ます。具体的には test/zlib/test_zlib.rb の
>test_invalid_new なんですが。
>
>書き込んでなければ警告しなくもいいだろうと思うんですが、書き
>込んだことがないとかチェックできるのかな。

ext/zlib 的には、何も書き込んでなくてもヘッダとフッタをつけて
出力するのが仕様のようです。(gzfile_writer_end)

io への書き込みで例外が出たときの対処がわからなかったのですが、

static void
gzfile_write_raw(gz)
    struct gzfile *gz;
{
    VALUE str;

    if (gz->z.buf_filled > 0) {
	str = zstream_detach_buffer(&gz->z);
	OBJ_TAINT(str);  /* for safe */
	rb_funcall(gz->io, id_write, 1, str);
	if ((gz->z.flags & GZFILE_FLAG_SYNC)
	    && rb_respond_to(gz->io, id_flush))
	    rb_funcall(gz->io, id_flush, 0);
    }
}

を見ると、io への書き込みで例外が出たらデータが失われるのは
許容されているようなので、これでどうでしょうか。

Index: zlib.c
===================================================================
RCS file: /src/ruby/ext/zlib/zlib.c,v
retrieving revision 1.30
diff -u -w -b -p -r1.30 zlib.c
--- zlib.c	7 Feb 2006 14:05:55 -0000	1.30
+++ zlib.c	7 Feb 2006 14:43:19 -0000
@@ -2274,12 +2274,11 @@ gzfile_ungetc(gz, c)
     gz->ungetc++;
 }
 
-static void
-gzfile_writer_end(gz)
-    struct gzfile *gz;
+static VALUE
+gzfile_writer_end_run(arg)
+    VALUE arg;
 {
-    if (ZSTREAM_IS_CLOSING(&gz->z)) return;
-    gz->z.flags |= ZSTREAM_FLAG_CLOSING;
+    struct gzfile *gz = (struct gzfile *)arg;
 
     if (!(gz->z.flags & GZFILE_FLAG_HEADER_FINISHED)) {
 	gzfile_make_header(gz);
@@ -2288,22 +2287,42 @@ gzfile_writer_end(gz)
     zstream_run(&gz->z, "", 0, Z_FINISH);
     gzfile_make_footer(gz);
     gzfile_write_raw(gz);
-    zstream_end(&gz->z);
+
+    return Qnil;
 }
 
 static void
-gzfile_reader_end(gz)
+gzfile_writer_end(gz)
     struct gzfile *gz;
 {
     if (ZSTREAM_IS_CLOSING(&gz->z)) return;
     gz->z.flags |= ZSTREAM_FLAG_CLOSING;
 
+    rb_ensure(gzfile_writer_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
+}
+
+static VALUE
+gzfile_reader_end_run(arg)
+    VALUE arg;
+{
+    struct gzfile *gz = (struct gzfile *)arg;
+
     if (GZFILE_IS_FINISHED(gz)
 	&& !(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
 	gzfile_check_footer(gz);
     }
 
-    zstream_end(&gz->z);
+    return Qnil;
+}
+
+static void
+gzfile_reader_end(gz)
+    struct gzfile *gz;
+{
+    if (ZSTREAM_IS_CLOSING(&gz->z)) return;
+    gz->z.flags |= ZSTREAM_FLAG_CLOSING;
+
+    rb_ensure(gzfile_reader_end_run, (VALUE)gz, zstream_end, (VALUE)&gz->z);
 }
 
 static void




In This Thread