Bug #5386
closedFiberオブジェクトのGC時にSEGV
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
Updated by ktsj (Kazuki Tsujimoto) over 13 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.
- vm.c (rb_thread_mark): rb_thread_t needs self to be marked.
[ruby-dev:44566] [Bug #5386]
Updated by ktsj (Kazuki Tsujimoto) over 13 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 ko1@atdot.net
イマイチ自信がないのですが,自分自身を mark するっておかしい気がします.
というわけで,次のような変更はどうでしょうか.
ありがとうございます。取り込んでおきました。
--
Kazuki Tsujimoto
Updated by ktsj (Kazuki Tsujimoto) over 13 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 13 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 13 years ago
辻本です。
このパッチで再現コードでのSEGVが起きなくなることを確認しました。
よければコミットしていただけないでしょうか。
Updated by nagachika (Tomoyuki Chikanaga) over 13 years ago
確認いただきありがとうございます。コミットしておきます。
ただ作業できるのが夜になってからなので、先にどなたかコミットして頂いてもわたしはかまいません。
Updated by nagachika (Tomoyuki Chikanaga) over 13 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.
- cont.c (cont_mark): mark original Thread object from saved_thread.
[ruby-dev:44567] [Bug #5386]