Project

General

Profile

Actions

Bug #5386

closed

FiberオブジェクトのGC時にSEGV

Added by ktsj (Kazuki Tsujimoto) over 12 years ago. Updated over 12 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 1.9.4dev (2011-10-01 trunk 33368) [x86_64-linux]
Backport:
[ruby-dev:44566]

Description

=begin
辻本です。

ポータブルな再現コードが作れていないのですが、
Ubuntu 10.04 x86_64にて以下のコードを実行すると
FiberオブジェクトをGCする処理の中でSEGVします。

require 'fiber'

1.times {
Fiber.new{}
}

2.times.map {|i|
Thread.new {
Fiber.new{}.resume
}.join
}.each {|t|
t.join
}

GC.start
GC.stress = true

1.times {
Fiber.new{}
}

バックトレースを添付します。

調べてみたところ、GC.stress設定後の1回目のマークフェーズで

Breakpoint 2, fiber_mark (ptr=0xad7130) at cont.c:265
(gdb) rp ((rb_fiber_t*)ptr)->cont->saved_thread.self
T_DATA(VM/thread): $1 = (struct RTypedData *) 0xaaf528

となっているFiberオブジェクトが、2回目のマークフェーズでは

Breakpoint 2, fiber_mark (ptr=0xad7130) at cont.c:265
(gdb) rp ((rb_fiber_t*)ptr)->cont->saved_thread.self
T_NONE: $2 = (struct RBasic *) 0xaaf528

となっており、saved_thread.selfのマーク漏れのようです。

以下の修正で直りました。

diff --git a/vm.c b/vm.c
index 665351b..2ab2b92 100644
--- a/vm.c
+++ b/vm.c
@@ -1735,6 +1735,7 @@ rb_thread_mark(void *ptr)
RUBY_MARK_UNLESS_NULL(th->first_proc);
if (th->first_proc) RUBY_MARK_UNLESS_NULL(th->first_args);

  • RUBY_MARK_UNLESS_NULL(th->self);
    RUBY_MARK_UNLESS_NULL(th->thgroup);
    RUBY_MARK_UNLESS_NULL(th->value);
    RUBY_MARK_UNLESS_NULL(th->errinfo);
    =end

Files

gdb-backtrace.log (12.5 KB) gdb-backtrace.log ktsj (Kazuki Tsujimoto), 10/02/2011 12:41 AM
ruby-backtrace.log (11.5 KB) ruby-backtrace.log ktsj (Kazuki Tsujimoto), 10/02/2011 12:41 AM
Actions #1

Updated by ktsj (Kazuki Tsujimoto) over 12 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r33369.
Kazuki, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


Updated by ktsj (Kazuki Tsujimoto) over 12 years ago

  • ruby -v changed from ruby 1.9.4dev (2011-10-01 trunk 33368) [x86_64-linux] to -

辻本です。

Subject: [ruby-dev:44567] Re: [ruby-dev:44566] [Ruby 1.9 - Bug#5386][Open] FiberオブジェクトのGC時にSEGV
From: SASADA Koichi

イマイチ自信がないのですが,自分自身を mark するっておかしい気がします.
というわけで,次のような変更はどうでしょうか.

ありがとうございます。取り込んでおきました。

--
Kazuki Tsujimoto

Updated by ktsj (Kazuki Tsujimoto) over 12 years ago

  • Status changed from Closed to Assigned
  • ruby -v changed from - to ruby 1.9.4dev (2011-10-01 trunk 33368) [x86_64-linux]

辻本です。

これらのコミットによってtest-allがSEGVするようになってしまった環境があるので
r33378で一旦revertしました。

http://u64.rubyci.org/~chkbuild/ruby-trunk/recent.html
http://c5664.rubyci.org/~chkbuild/ruby-trunk/recent.html
http://fbsd.rubyci.org/~chkbuild/ruby-trunk/recent.html

Updated by nagachika (Tomoyuki Chikanaga) over 12 years ago

以下でどうでしょうか?
test-all の test_many_fibers_with_threads がSEGVするというのは起きなくなるのは確認しましたが、元々の再現スクリプトでは手元で SEGV を発生させられていないのでそちらは未確認です。

なお cont->saved_thread の構造体は cont->saved_thread.self が指しているオブジェクトが wrap している構造体のコピーで、アドレスは別物なのでそれぞれ別にマークしないといけない、ということなのかなぁと思いましたが、具体的に何がマーク漏れで困ってるのかはちゃんと確認していません。

diff --git a/cont.c b/cont.c
index 3e68d89..22944d6 100644
--- a/cont.c
+++ b/cont.c
@@ -139,6 +139,7 @@ cont_mark(void *ptr)
rb_context_t *cont = ptr;
rb_gc_mark(cont->value);
rb_thread_mark(&cont->saved_thread);

  • rb_gc_mark(cont->saved_thread.self);

    if (cont->vm_stack) {
    #ifdef CAPTURE_JUST_VALID_VM_STACK

Updated by ktsj (Kazuki Tsujimoto) over 12 years ago

辻本です。

このパッチで再現コードでのSEGVが起きなくなることを確認しました。
よければコミットしていただけないでしょうか。

Updated by nagachika (Tomoyuki Chikanaga) over 12 years ago

確認いただきありがとうございます。コミットしておきます。
ただ作業できるのが夜になってからなので、先にどなたかコミットして頂いてもわたしはかまいません。

Actions #7

Updated by nagachika (Tomoyuki Chikanaga) over 12 years ago

  • Status changed from Assigned to Closed

This issue was solved with changeset r33410.
Kazuki, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0