[#11952] NORETURN — "Nobuyoshi.Nakada" <nobu.nakada@...>

なかだです。

24 messages 2001/01/10
[#11956] Re: NORETURN — WATANABE Hirofumi <eban@...> 2001/01/10

わたなべです.

[#11957] Re: NORETURN — matz@... (Yukihiro Matsumoto) 2001/01/10

まつもと ゆきひろです

[#11958] Re: NORETURN — WATANABE Hirofumi <eban@...> 2001/01/10

わたなべです.

[#11959] CVS branches (Re: Re: NORETURN) — matz@... (Yukihiro Matsumoto) 2001/01/10

[#12087] string#index, gsub, []= のバグ? — Beyond <beyond@...>

18 messages 2001/01/27
[#12091] Re: string#index, gsub, []= のバグ? — matz@... (Yukihiro Matsumoto) 2001/01/27

まつもと ゆきひろです

[ruby-dev:11916] Re: core dump with GC and Ruby/zlib

From: Ueno Katsuhiro <unnie@...>
Date: 2001-01-04 15:32:56 UTC
List: ruby-dev #11916
うえの@ぶるーすかいです。

On Thu, 4 Jan 2001 19:48:10 +0900
Tanaka Akira <akr@m17n.org> wrote:

> 次のスクリプトが core を吐きます。
>
> Z(2):akr@flux% cat tst
> #!/usr/local/bin/ruby
>
> require 'zlib';
>
> f = open('z', 'w')
> p f.id
>
> s = "a"
> begin
>   s = s.dup
> end while s.id < f.id
>
> g = GzipWriter.new(f)
> p g.id
>
> print "script ends.\n"
snip..
> ruby は [BUG] だと述べていますが、これは Ruby と Ruby/zlib のどちらの
> BUG なのでしょう?

Ruby のバグっぽいです。
g が解放 (= close) される前に f が解放されています。

で、gc.c (in ruby-1.6.2.tar.gz) の 1247 行目付近の

  else if (BUILTIN_TYPE(p) == T_FILE) {
    p->as.free.flag = 0;                          ← コレ
    rb_io_fptr_finalize(RANY(p)->as.file.fptr);
  }

で f の型が T_FILE でなくなり、さらにその後 g が解放されるときに
すでに解放されている f の write メソッドを呼んでしまい、
io.c の 236 行付近のテストにひっかかり

  if (TYPE(io) != T_FILE) {
      /* port is not IO, call write method for it. */
      return rb_funcall(io, id_write, 1, str);
  }

無限ループしてしまっているようです。

T_DATA を解放した後で T_FILE を解放するようにすればいいのかな?

--- gc.c.orig	Fri Dec 22 12:21:56 2000
+++ gc.c	Fri Jan  5 00:24:33 2001
@@ -1242,7 +1242,13 @@
 		p->as.free.flag = 0;
 		(*RANY(p)->as.data.dfree)(DATA_PTR(p));
 	    }
-	    else if (BUILTIN_TYPE(p) == T_FILE) {
+	    p++;
+	}
+    }
+    for (i = 0; i < heaps_used; i++) {
+	p = heaps[i]; pend = p + HEAP_SLOTS;
+	while (p < pend) {
+	    if (BUILTIN_TYPE(p) == T_FILE) {
 		p->as.free.flag = 0;
 		rb_io_fptr_finalize(RANY(p)->as.file.fptr);
 	    }


core を吐くのは、スクリプト終了時の最後の GC で finalizer の中で
例外が起きると prot_tag が 0 のために JUMP_TAG で segv になるのが
原因のようです。

これも

> # ちなみに、これと直接には関係ありませんが
> #   ruby -e 'require "zlib"; f = GzipWriter.new(1); f.print "a\n"'
> # が core を吐くのは Ruby/zlib の問題だと思う。

同じ原因です。
finalize 中に Fixnum#write を呼んだために NameError 例外が発生しています。

うーん、finalizer の中では例外が起きるようなことは
しないほうがいいんでしょうか?


-=====--===-
   うえの かつひろ @ BLUE-SKYNET    <unnie@blue.sky.or.jp>  --=
---=----===-                    http://www.blue.sky.or.jp/  -==

In This Thread