https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112011-07-21T10:47:10ZRuby Issue Tracking SystemRuby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=194252011-07-21T10:47:10Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul><li><strong>Category</strong> set to <i>core</i></li><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>nahi (Hiroshi Nakamura)</i></li><li><strong>Target version</strong> set to <i>1.9.2</i></li></ul><p>Confirmed the SEGV on my machine. I'll investigate it.</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=194272011-07-21T10:55:59Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul><li><strong>Target version</strong> changed from <i>1.9.2</i> to <i>1.9.3</i></li></ul><p>I get SEGV with ruby 1.9.3dev (2011-07-21 revision 32592) [x86_64-linux] as well. Still investigating.</p>
<p>Note: Don't forget to backport when we fixes it.</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=194332011-07-21T13:57:37Zkosaki (Motohiro KOSAKI)kosaki.motohiro@gmail.com
<ul><li><strong>Priority</strong> changed from <i>Normal</i> to <i>5</i></li></ul> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=195142011-07-22T11:47:32Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul></ul><p>Can someone enlighten me to find the bug?</p>
<a name="Heres-a-way-to-replicate-the-bug-4-steps-Im-on-Ubuntu-1104-64bit"></a>
<h2 >Here's a way to replicate the bug. 4 steps. I'm on Ubuntu 11.04 64bit.<a href="#Heres-a-way-to-replicate-the-bug-4-steps-Im-on-Ubuntu-1104-64bit" class="wiki-anchor">¶</a></h2>
<a name="1-extract-the-attached-app"></a>
<h1 >1. extract the attached app<a href="#1-extract-the-attached-app" class="wiki-anchor">¶</a></h1>
<p>% unzip segfault.zip<br>
% cd segfault</p>
<a name="2-install-bundler-via-rubygems"></a>
<h1 >2. install bundler via rubygems<a href="#2-install-bundler-via-rubygems" class="wiki-anchor">¶</a></h1>
<p>% gem install bundler --user-install<br>
% export PATH=$PATH:/home/nahi/.gem/ruby/1.9.1/bin</p>
<a name="3-run-bundle-to-install-gems-to-ruby"></a>
<h1 >3. run bundle to install gems to ./ruby<a href="#3-run-bundle-to-install-gems-to-ruby" class="wiki-anchor">¶</a></h1>
<p>% bundle install --path=.</p>
<a name="4-execute-it"></a>
<h1 >4. execute it<a href="#4-execute-it" class="wiki-anchor">¶</a></h1>
<a name="-ruby-rbundler-e-Bundlersetup-require-rspeccore-RSpecCoreRunnerrunspec-stderr-stdout"></a>
<h2 >% ruby -rbundler -e 'Bundler.setup; require "rspec/core"; RSpec::Core::Runner.run(["spec"], $stderr, $stdout)'<a href="#-ruby-rbundler-e-Bundlersetup-require-rspeccore-RSpecCoreRunnerrunspec-stderr-stdout" class="wiki-anchor">¶</a></h2>
<a name="And-heres-my-gdb-session"></a>
<h2 >And here's my gdb session.<a href="#And-heres-my-gdb-session" class="wiki-anchor">¶</a></h2>
<p>% gdb /usr/local/bin/ruby<br>
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2<br>
Copyright (C) 2010 Free Software Foundation, Inc.<br>
License GPLv3+: GNU GPL version 3 or later <a href="http://gnu.org/licenses/gpl.html" class="external">http://gnu.org/licenses/gpl.html</a><br>
This is free software: you are free to change and redistribute it.<br>
There is NO WARRANTY, to the extent permitted by law. Type "show copying"<br>
and "show warranty" for details.<br>
This GDB was configured as "x86_64-linux-gnu".<br>
For bug reporting instructions, please see:<br>
<a href="http://www.gnu.org/software/gdb/bugs/" class="external">http://www.gnu.org/software/gdb/bugs/</a>...<br>
Reading symbols from /usr/local/bin/ruby...done.<br>
(gdb) run -rbundler -e 'Bundler.setup; require "rspec/core"; RSpec::Core::Runner.run(["spec"], $stderr, $stdout)'<br>
Starting program: /usr/local/bin/ruby -rbundler -e 'Bundler.setup; require "rspec/core"; RSpec::Core::Runner.run(["spec"], $stderr, $stdout)'<br>
[Thread debugging using libthread_db enabled]<br>
[New Thread 0x7ffff6682700 (LWP 13255)]<br>
[Thread 0x7ffff6682700 (LWP 13255) exited]<br>
[New Thread 0x7ffff6682700 (LWP 13257)]</p>
<h2>Program received signal SIGSEGV, Segmentation fault.<br>
0x00007ffff7ab5c99 in st_foreach (table=0x28b5020, func=0x7ffff7a0c230 <mark_entry>, arg=140737488315296) at ../st.c:745<br>
745 key = (st_data_t)table->bins[i*2];<br>
(gdb) where<br>
#0 0x00007ffff7ab5c99 in st_foreach (table=0x28b5020, func=0x7ffff7a0c230 <mark_entry>, arg=140737488315296) at ../st.c:745<br>
#1 0x00007ffff7a0be88 in mark_tbl (objspace=0x6038a0, ptr=19563040, lev=5) at ../gc.c:1445<br>
#2 gc_mark_children (objspace=0x6038a0, ptr=19563040, lev=5) at ../gc.c:1801<br>
#3 0x00007ffff7a0b8d8 in gc_mark_children (objspace=0x6038a0, ptr=35333200, lev=4) at ../gc.c:1795<br>
#4 0x00007ffff7a0b8d8 in gc_mark_children (objspace=0x6038a0, ptr=35333280, lev=3) at ../gc.c:1795<br>
#5 0x00007ffff7a0c1d6 in mark_const_entry_i (key=, ce=, data=)<br>
at ../gc.c:1562<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed behind-schedule" title="Bug: sprintf() of %f on Windows(MSVCRT) (Closed)" href="https://redmine.ruby-lang.org/issues/6">#6</a> 0x00007ffff7ab5d1c in st_foreach (table=0x19131a0, func=0x7ffff7a0c1c0 <mark_const_entry_i>, arg=140737488315616)<br>
at ../st.c:787<br>
#7 0x00007ffff7a0bead in mark_const_tbl (objspace=0x6038a0, ptr=10364280, lev=2) at ../gc.c:1573<br>
#8 gc_mark_children (objspace=0x6038a0, ptr=10364280, lev=2) at ../gc.c:1802<br>
#9 0x00007ffff7a0bb7e in gc_mark_children (objspace=0x6038a0, ptr=27521040, lev=1) at ../gc.c:1688<br>
#10 0x00007ffff7b02bb5 in iseq_mark (ptr=0x2398250) at ../iseq.c:106<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: prelude.c compilation problem on mswin32 (Closed)" href="https://redmine.ruby-lang.org/issues/11">#11</a> 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=30252840, lev=3) at ../gc.c:1839<br>
#12 0x00007ffff7a0c2c8 in mark_method_entry (key=, me=, data=)<br>
at ../gc.c:1506<br>
#13 mark_method_entry_i (key=, me=, data=) at ../gc.c:1530<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: test issue for ruby-1.9 (Closed)" href="https://redmine.ruby-lang.org/issues/14">#14</a> 0x00007ffff7ab5d1c in st_foreach (table=0x23d4f70, func=0x7ffff7a0c270 <mark_method_entry_i>, arg=140737488315968)<br>
at ../st.c:787<br>
#15 0x00007ffff7a0be59 in mark_m_tbl (objspace=0x6038a0, ptr=21024760, lev=2) at ../gc.c:1541<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: example issue for ruby-1.8 (Closed)" href="https://redmine.ruby-lang.org/issues/16">#16</a> gc_mark_children (objspace=0x6038a0, ptr=21024760, lev=2) at ../gc.c:1800<br>
<a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: deadlock detection for 1.9 (Closed)" href="https://redmine.ruby-lang.org/issues/17">#17</a> 0x00007ffff7a0b8d8 in gc_mark_children (objspace=0x6038a0, ptr=41607400, lev=1) at ../gc.c:1795<br>
#18 0x00007ffff7a0df82 in mark_locations_array (start=, end=) at ../gc.c:1401<br>
#19 gc_mark_locations (start=, end=) at ../gc.c:1414<br>
#20 rb_gc_mark_locations (start=, end=) at ../gc.c:1420<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: should terminate @receiver_thread of Net::IMAP safely (Closed)" href="https://redmine.ruby-lang.org/issues/21">#21</a> 0x00007ffff7b0768e in env_mark (ptr=0x2bfda70) at ../vm.c:238<br>
#22 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=41607040, lev=1) at ../gc.c:1839<br>
#23 0x00007ffff7a0df82 in mark_locations_array (start=, end=) at ../gc.c:1401<br>
#24 gc_mark_locations (start=, end=) at ../gc.c:1414<br>
#25 rb_gc_mark_locations (start=, end=) at ../gc.c:1420<br>
<a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: [DOC] Typo in enumerator.c (Enumerator.new) (Closed)" href="https://redmine.ruby-lang.org/issues/26">#26</a> 0x00007ffff7b0768e in env_mark (ptr=0x2562950) at ../vm.c:238<br>
#27 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=41607000, lev=1) at ../gc.c:1839<br>
#28 0x00007ffff79fc9d5 in proc_mark (ptr=0x277bf80) at ../proc.c:53<br>
#29 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=41606920, lev=2) at ../gc.c:1839<br>
#30 0x00007ffff7a0c2fc in mark_method_entry (key=, me=, data=)<br>
at ../gc.c:1509<br>
#31 mark_method_entry_i (key=, me=, data=) at ../gc.c:1530<br>
#32 0x00007ffff7ab5d1c in st_foreach (table=0x25b2070, func=0x7ffff7a0c270 <mark_method_entry_i>, arg=140737488316608)<br>
at ../st.c:787<br>
#33 0x00007ffff7a0be59 in mark_m_tbl (objspace=0x6038a0, ptr=33366880, lev=1) at ../gc.c:1541<br>
#34 gc_mark_children (objspace=0x6038a0, ptr=33366880, lev=1) at ../gc.c:1800<br>
#35 0x00007ffff7b02ba5 in iseq_mark (ptr=0x27528f0) at ../iseq.c:107<br>
#36 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=33147080, lev=2) at ../gc.c:1839<br>
#37 0x00007ffff7a0be2b in gc_mark_children (objspace=0x6038a0, ptr=, lev=1) at ../gc.c:1815<br>
#38 0x00007ffff7b02bf5 in iseq_mark (ptr=0x27520f0) at ../iseq.c:102<br>
#39 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=33147560, lev=2) at ../gc.c:1839<br>
#40 0x00007ffff7a0be2b in gc_mark_children (objspace=0x6038a0, ptr=, lev=1) at ../gc.c:1815<br>
#41 0x00007ffff7b02bf5 in iseq_mark (ptr=0x2751db0) at ../iseq.c:102<br>
#42 0x00007ffff7a0baba in gc_mark_children (objspace=0x6038a0, ptr=33148280, lev=5) at ../gc.c:1839<br>
#43 0x00007ffff7a0c2c8 in mark_method_entry (key=, me=, data=)<br>
at ../gc.c:1506<br>
#44 mark_method_entry_i (key=, me=, data=) at ../gc.c:1530<br>
#45 0x00007ffff7ab5d1c in st_foreach (table=0x27e52d0, func=0x7ffff7a0c270 <mark_method_entry_i>, arg=140737488317232)<br>
---Type to continue, or q to quit---quit<br>
at ../st.Quit<br>
(gdb) up 2<br>
#2 gc_mark_children (objspace=0x6038a0, ptr=19563040, lev=5) at ../gc.c:1801<br>
1801 mark_tbl(objspace, RCLASS_IV_TBL(obj), lev);<br>
(gdb) p *obj<br>
$1 = {as = {free = {flags = 4130, next = 0x665b20}, basic = {flags = 4130, klass = 6708000}, object = {basic = {flags = 4130,<br>
klass = 6708000}, as = {heap = {numiv = 42751520, ivptr = 0x2af3720, iv_index_tbl = 0x0}, ary = {42751520, 45037344,<br>
0}}}, klass = {basic = {flags = 4130, klass = 6708000}, ptr = 0x28c5620, m_tbl = 0x2af3720, iv_index_tbl = 0x0},<br>
flonum = {basic = {flags = 4130, klass = 6708000}, float_value = 2.1122057339494968e-316}, string = {basic = {<br>
flags = 4130, klass = 6708000}, as = {heap = {len = 42751520, ptr = 0x2af3720 "\340\263\333\367\377\177", aux = {<br>
capa = 0, shared = 0}}, ary = " V\214\002\000\000\000\000 7\257\002", '\000' <repeats 11 times>}}, array = {<br>
basic = {flags = 4130, klass = 6708000}, as = {heap = {len = 42751520, aux = {capa = 45037344, shared = 45037344},<br>
ptr = 0x0}, ary = {42751520, 45037344, 0}}}, regexp = {basic = {flags = 4130, klass = 6708000}, ptr = 0x28c5620,<br>
src = 45037344, usecnt = 0}, hash = {basic = {flags = 4130, klass = 6708000}, ntbl = 0x28c5620, iter_lev = 45037344,<br>
ifnone = 0}, data = {basic = {flags = 4130, klass = 6708000}, dmark = 0x28c5620, dfree = 0x2af3720, data = 0x0},<br>
typeddata = {basic = {flags = 4130, klass = 6708000}, type = 0x28c5620, typed_flag = 45037344, data = 0x0}, rstruct = {<br>
basic = {flags = 4130, klass = 6708000}, as = {heap = {len = 42751520, ptr = 0x2af3720}, ary = {42751520, 45037344,<br>
0}}}, bignum = {basic = {flags = 4130, klass = 6708000}, as = {heap = {len = 42751520, digits = 0x2af3720}, ary = {<br>
42751520, 0, 45037344, 0, 0, 0}}}, file = {basic = {flags = 4130, klass = 6708000}, fptr = 0x28c5620}, node = {<br>
flags = 4130, nd_reserved = 6708000, u1 = {node = 0x28c5620, id = 42751520, value = 42751520, cfunc = 0x28c5620,<br>
tbl = 0x28c5620}, u2 = {node = 0x2af3720, id = 45037344, argc = 45037344, value = 45037344}, u3 = {node = 0x0, id = 0,<br>
state = 0, entry = 0x0, cnt = 0, value = 0}}, match = {basic = {flags = 4130, klass = 6708000}, str = 42751520,<br>
rmatch = 0x2af3720, regexp = 0}, rational = {basic = {flags = 4130, klass = 6708000}, num = 42751520, den = 45037344},<br>
complex = {basic = {flags = 4130, klass = 6708000}, real = 42751520, imag = 45037344}}}<br>
(gdb) p 4130 & 0x1f<br>
$2 = 2<br>
(gdb) p obj.as.klass<br>
$3 = {basic = {flags = 4130, klass = 6708000}, ptr = 0x28c5620, m_tbl = 0x2af3720, iv_index_tbl = 0x0}<br>
(gdb) p obj.as.klass.m_tbl<br>
$4 = (struct st_table *) 0x2af3720<br>
(gdb) p *obj.as.klass.m_tbl<br>
$5 = {type = 0x7ffff7dbb3e0, num_bins = 11, entries_packed = 1, num_entries = 0, bins = 0x28c1730, head = 0x0, tail = 0x0}<br>
(gdb) p obj.as.klass.m_tbl.bins[0]<br>
$6 = (struct st_table_entry *) 0x0<br>
(gdb)</h2> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=195572011-07-23T06:53:51Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Hiroshi Nakamura <a href="mailto:nakahiro@gmail.com" class="email">nakahiro@gmail.com</a> wrote:</p>
<blockquote>
<p>Can someone enlighten me to find the bug?</p>
</blockquote>
<p>I started looking into this, too, but haven't found the exact<br>
cause/solution, either.</p>
<p>It does not seem to be in the tinytds nor bcrypt C extensions,<br>
I put in early returns for each extensions' Init_* functions<br>
to avoid hitting C code outside of Ruby trunk.</p>
<p>It seems to be related to how the parser/loader sets up (or fails to set<br>
up) objects for GC. Some backtraces I get are very deep inside gc_mark*<br>
functions (500-700+ C stack frames).</p>
<p>I cannot reproduce this with GC.disable or a huge malloc limit<br>
(RUBY_GC_MALLOC_LIMIT=800000000).</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=195582011-07-23T07:53:07Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul><li><strong>ruby -v</strong> changed from <i>ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]</i> to <i>-</i></li></ul><p>On Jul 22, 2011, at 2:41 PM, Eric Wong wrote:</p>
<blockquote>
<p>Hiroshi Nakamura <a href="mailto:nakahiro@gmail.com" class="email">nakahiro@gmail.com</a> wrote:</p>
<blockquote>
<p>Can someone enlighten me to find the bug?</p>
</blockquote>
<p>I started looking into this, too, but haven't found the exact<br>
cause/solution, either.</p>
<p>It does not seem to be in the tinytds nor bcrypt C extensions,<br>
I put in early returns for each extensions' Init_* functions<br>
to avoid hitting C code outside of Ruby trunk.</p>
<p>It seems to be related to how the parser/loader sets up (or fails to set<br>
up) objects for GC. Some backtraces I get are very deep inside gc_mark*<br>
functions (500-700+ C stack frames).</p>
<p>I cannot reproduce this with GC.disable or a huge malloc limit<br>
(RUBY_GC_MALLOC_LIMIT=800000000).</p>
</blockquote>
<p>Does GC.stress help?</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=195602011-07-23T07:59:07Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Eric Hodel <a href="mailto:drbrain@segment7.net" class="email">drbrain@segment7.net</a> wrote:</p>
<blockquote>
<p>Does GC.stress help?</p>
</blockquote>
<p>I tried it for a while but lost patience while waiting. I suppose<br>
I'll try it again while I poke at other things...</p>
<p>--<br>
Eric Wong</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=195612011-07-23T08:53:06Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul></ul><p>On Sat, Jul 23, 2011 at 07:56, Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a> wrote:</p>
<blockquote>
<blockquote>
<p>Does GC.stress help?</p>
</blockquote>
<p>I tried it for a while but lost patience while waiting. Â I suppose<br>
I'll try it again while I poke at other things...</p>
</blockquote>
<p>Yeah, I waited 2 hours before I quit the way. :-(</p>
<p>Adding rb_gc() to several part at load.c but I still cannot narrow<br>
down where the broken object created...</p>
<p>Regards,<br>
// NaHi</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196012011-07-24T09:30:50Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul></ul><p>Random note;</p>
<ul>
<li>SEGV on trunk, ruby_1_9_3 and 1.9.2-p280</li>
<li>SEGV on x86_64-linux but NOT on x86_64-darwin10.8.0 according to <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/404">@nagachika (Tomoyuki Chikanaga)</a></li>
<li>SEGV at GC mark or sweep, and the broken object looks like a singleton class object</li>
<li>SEGV caused at autoload from autoload from autoload... or at finalizing VM at exit.</li>
<li>slight change of code, different location of SEGV.</li>
<li>lack of RB_GC_GUARD for a Node which is used in particular code?</li>
</ul> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196032011-07-24T10:53:06Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>Hello,</p>
<p>Thank you for the reproducing process. I could also comfirmed it.<br>
This is one of the most difficult bug that I have seen...</p>
<p>In short, I've not solved this issue, but I found valgrind with -O0<br>
enlightens us the (maybe) important point:</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196052011-07-24T12:23:06Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>Follow-up.</p>
<p>I found activesupport uses UnboundMethod and #bind to check whether<br>
a class instance is singleton or not.</p>
<p>102 def singleton_class?<br>
103 # in case somebody is crazy enough to overwrite allocate<br>
104 allocate = Class.instance_method(:allocate)<br>
105 # object.class always points to a real (non-singleton) class<br>
106 allocate.bind(self).call.class != self<br>
107 rescue TypeError<br>
108 # MRI/YARV/JRuby all disallow creating new instances of a<br>
singleton class<br>
109 true<br>
110 end</p>
<p>Of course, this is not a fault of activesupport, but this seems<br>
one factor to this SEGV.<br>
If you need to work around this issue right now, the following patch<br>
for activesupport might work.</p>
<p>$ diff -u active_support/core_ext/class/attribute.rb.orig<br>
active_support/core_ext/class/attribute.rb<br>
--- active_support/core_ext/class/attribute.rb.orig 2011-07-24<br>
11:51:32.690364370 +0900<br>
+++ active_support/core_ext/class/attribute.rb 2011-07-24<br>
11:51:35.990380754 +0900<br>
@@ -100,6 +100,7 @@</p>
<pre><code>private
def singleton_class?
</code></pre>
<ul>
<li>return !ancestors.include?(self)
<a name="in-case-somebody-is-crazy-enough-to-overwrite-allocate"></a>
<h1 >in case somebody is crazy enough to overwrite allocate<a href="#in-case-somebody-is-crazy-enough-to-overwrite-allocate" class="wiki-anchor">¶</a></h1>
allocate = Class.instance_method(:allocate)
<a name="objectclass-always-points-to-a-real-non-singleton-class"></a>
<h1 >object.class always points to a real (non-singleton) class<a href="#objectclass-always-points-to-a-real-non-singleton-class" class="wiki-anchor">¶</a></h1>
</li>
</ul>
<p>At least, SEGV does not occur with this patch on my machine.<br>
Could anyone please try it?</p>
<p>Again, this is not a fault of activesupport. This is just workaround<br>
patch.</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196062011-07-24T12:23:07Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>2011/7/24 Yusuke ENDOH <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a>:</p>
<blockquote>
<p>If you need to work around this issue right now, the following patch<br>
for activesupport might work.</p>
</blockquote>
<p>FYI, Aaron fixed activesupport in trunk so quickly :-)</p>
<p><a href="https://github.com/rails/rails/commit/cdc4274931c2d6bafdf2b97f7e4ecedf89a8202e" class="external">https://github.com/rails/rails/commit/cdc4274931c2d6bafdf2b97f7e4ecedf89a8202e</a></p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196122011-07-24T21:09:35Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>File</strong> <a href="/attachments/1918">5047.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/1918/5047.patch">5047.patch</a> added</li><li><strong>Assignee</strong> changed from <i>nahi (Hiroshi Nakamura)</i> to <i>ko1 (Koichi Sasada)</i></li></ul><p>I probably managed to fix this issue.<br>
Could anyone try the attached patch?<br>
ko1: May I commit it?</p>
<p>This problem is caused by the combination of the wrong design<br>
of Method class and lack of YARV method entry marking, with<br>
obfuscated by conservative GC and Fiber's machine stack...</p>
<p>Each method has struct rb_method_entry_t. The struct is free'd<br>
when its method is removed, except the method is "live" (i.e.,<br>
method being now executed).<br>
To prevent live rb_method_entry_t from being free'd, YARV<br>
traverses the YARV stack and marks each live rb_method_entry_t<br>
at GC marking phase.<br>
However, when the method is BMETHOD (i.e., Method#call), the<br>
system does not work correctly because rb_method_entry_t is<br>
embedded in the internal structure of Method class (i.e.,<br>
struct METHOD). The rb_method_entry_t is free'd when the Method<br>
object is GC'd, even if the YARV attempts to prevent it.</p>
<p>My patch separates rb_method_entry_t from struct METHOD,</p>
<p>struct METHOD {<br>
VALUE recv;<br>
VALUE rclass;<br>
ID id;</p>
<ul>
<li>rb_method_entry_t me;</li>
</ul>
<ul>
<li>rb_method_entry_t *me;<br>
};</li>
</ul>
<p>and marks them explicitly at each marking phase.</p>
<p>I tried to create a small test for this issue, but didn't<br>
succeeded because of conservative GC.</p>
<p>The following is Japanese translation.</p>
<p>拙い英語で書いただけだと後でわからなくなる自信があるので日本語でも<br>
簡単に。</p>
<p>要は、struct METHOD 中の rb_method_entry_t をポインタにするパッチ<br>
です。<br>
rb_method_entry_t は YARV スタックに載っている限りは free しちゃ<br>
ダメなんですが、struct METHOD に埋めこまれた状態だと、Method オブ<br>
ジェクトが解放された時にあわせて free されてしまって、でもスタック<br>
には乗ってるので解放領域を mark とかしてメモリが破壊されているので<br>
した。<br>
rb_method_entry_t をポインタに切り分けて別途 malloc するようにし<br>
たら直った気がします。</p>
<p>小さい例も作りたかったんですが、conservative GC がなかなか Method<br>
を解放してくれず、作れませんでした。</p>
<p>rb_method_entry_t を作ったのはささださんなので、一応ささださんに<br>
確認して欲しいです。</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196232011-07-25T03:23:10Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a> wrote:</p>
<blockquote>
<p>I probably managed to fix this issue.<br>
Could anyone try the attached patch?</p>
</blockquote>
<p>Seems to work for me.</p>
Explanation is good and makes sense to me. Thanks!
<p>sidenote: I didn't realize xmalloc() (via rb_unlink_method_entry) is<br>
safe/allowed inside bm_free(); but apparently it's only rb_new_obj()<br>
that's prevented inside GC.</p>
<p>--<br>
Eric Wong</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196272011-07-25T06:34:51Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul></ul><p>Yusuke Endoh wrote:</p>
<blockquote>
<p>I probably managed to fix this issue.<br>
Could anyone try the attached patch?<br>
ko1: May I commit it?</p>
</blockquote>
<p>With the patch, both trunk and ruby_1_9_3 run without SEGV. My hat's off to you for your exhausting job.</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196282011-07-25T07:29:06Zko1 (Koichi Sasada)
<ul></ul><p>(2011/07/25 6:35), Hiroshi Nakamura wrote:</p>
<blockquote>
<p>With the patch, both trunk and ruby_1_9_3 run without SEGV. My hat's off to you for your exhausting job.</p>
</blockquote>
<p>Me too. Thanks a lot.</p>
<p>--<br>
// SASADA Koichi at atdot dot net</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196292011-07-25T08:38:05Zkosaki (Motohiro KOSAKI)kosaki.motohiro@gmail.com
<ul></ul><blockquote>
<blockquote>
<p>With the patch, both trunk and ruby_1_9_3 run without SEGV. My hat's off to you for your exhausting job.</p>
</blockquote>
<p>Me too. Thanks a lot.</p>
</blockquote>
<p>Me too. You are great.</p>
<p>Offtopic: now 1.9.3 have two high priority (i.e. crash related) bug, <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Re: socket related errors on chkbuild (Closed)" href="https://redmine.ruby-lang.org/issues/5039">#5039</a> and this. And this was<br>
most mysterious and difficult one. Now I don't doubt 1.9.3 is going to be released on a planned schedule.<br>
Of course, there still are several normal priority bugs. we'll do our best.</p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196712011-07-25T22:29:12Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>Thank you for the trying the patch.<br>
Nobu pointed out that the patch may cause memory leak.<br>
I'll commit a revised version soon.</p>
<p>2011/7/25 Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a>:</p>
<blockquote>
<p>sidenote: I didn't realize xmalloc() (via rb_unlink_method_entry) is<br>
safe/allowed inside bm_free(); but apparently it's only rb_new_obj()<br>
that's prevented inside GC.</p>
</blockquote>
<p>Good point. I was not aware of this.<br>
Indeed, GC does not occur recursively even if vm_xmalloc is called<br>
during GC. But NoMemoryError may be raised from bm_free()... It<br>
will probably make the interpreter state inconsistent, so I guess<br>
it is not possible to sanely continue the execution by rescue'ing<br>
the exception.<br>
But I have no solution about the case. Frankly speaking, I think<br>
we can do nothing if just few dozens byte allocation is failed.</p>
<p>2011/7/25 Motohiro KOSAKI <a href="mailto:kosaki.motohiro@gmail.com" class="email">kosaki.motohiro@gmail.com</a>:</p>
<blockquote>
<blockquote>
<blockquote>
<p>With the patch, both trunk and ruby_1_9_3 run without SEGV. My hat's off to you for your exhausting job.</p>
</blockquote>
<p>Me too. Thanks a lot.</p>
</blockquote>
<p>Me too. You are great.</p>
</blockquote>
<p>Thanks for the compliment!</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196732011-07-25T23:23:17Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Yusuke ENDOH <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a> wrote:</p>
<blockquote>
<p>2011/7/25 Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a>:</p>
<blockquote>
<p>sidenote: I didn't realize xmalloc() (via rb_unlink_method_entry) is<br>
safe/allowed inside bm_free(); but apparently it's only rb_new_obj()<br>
that's prevented inside GC.</p>
</blockquote>
<p>Good point. I was not aware of this.<br>
Indeed, GC does not occur recursively even if vm_xmalloc is called<br>
during GC. But NoMemoryError may be raised from bm_free()... It<br>
will probably make the interpreter state inconsistent, so I guess<br>
it is not possible to sanely continue the execution by rescue'ing<br>
the exception.<br>
But I have no solution about the case. Frankly speaking, I think<br>
we can do nothing if just few dozens byte allocation is failed.</p>
</blockquote>
<p>We can pre-allocate the unlinked_method_entry_list_entry struct<br>
in the METHOD struct and then push it into unlinked_method_entry_list<br>
in bm_free (untested patch below):</p>
<p>--- a/proc.c<br>
+++ b/proc.c<br>
@@ -19,6 +19,7 @@ struct METHOD {<br>
VALUE rclass;<br>
ID id;<br>
rb_method_entry_t *me;</p>
<ul>
<li>struct unlinked_method_entry_list_entry *ume;<br>
};</li>
</ul>
<p>VALUE rb_cUnboundMethod;<br>
@@ -868,7 +869,11 @@ static void<br>
bm_free(void *ptr)<br>
{<br>
struct METHOD *data = ptr;</p>
<ul>
<li>rb_unlink_method_entry(data->me);</li>
</ul>
<ul>
<li>struct unlinked_method_entry_list_entry *ume = data->ume;</li>
<li>
<li>ume->me = data->me;</li>
<li>ume->next = GET_VM()->unlinked_method_entry_list;</li>
<li>GET_VM()->unlinked_method_entry_list = ume;<br>
xfree(ptr);<br>
}</li>
</ul>
<p>@@ -978,6 +983,7 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)<br>
data->me = me2;<br>
*data->me = *me;<br>
data->me->def->alias_count++;</p>
<ul>
<li>
<p>data->ume = ALLOC(struct unlinked_method_entry_list_entry);</p>
<p>OBJ_INFECT(method, klass);</p>
</li>
</ul>
<p>@@ -1088,6 +1094,7 @@ method_unbind(VALUE obj)<br>
*data->me = *orig->me;<br>
if (orig->me->def) orig->me->def->alias_count++;<br>
data->rclass = orig->rclass;</p>
<ul>
<li>
<p>data->ume = ALLOC(struct unlinked_method_entry_list_entry);<br>
OBJ_INFECT(method, obj);</p>
<p>return method;<br>
--<br>
Eric Wong</p>
</li>
</ul> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196742011-07-25T23:29:30Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>This issue was solved with changeset r32669.<br>
Jack, thank you for reporting this issue.<br>
Your contribution to Ruby is greatly appreciated.<br>
May Ruby be with you.</p>
<hr>
<ul>
<li>proc.c (struct METHOD), gc.c (gc_marks), vm_method.c<br>
(rb_gc_mark_unlinked_live_method_entries): fix SEGV bug.<br>
rb_method_entry_t was free'd even when the method is still on the<br>
stack if it is BMETHOD (i.e., Method#call). This is because<br>
rb_method_entry_t is embedded in struct METHOD. This commit<br>
separates them and marks the live method entries.<br>
See <a href="/issues/5047">[ruby-core:38449]</a> in detail. fix [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Segfault (most likely involving require) (Closed)" href="https://redmine.ruby-lang.org/issues/5047">#5047</a>] <a href="/issues/5047">[ruby-core:38171]</a></li>
</ul> Ruby master - Bug #5047: Segfault (most likely involving require)https://redmine.ruby-lang.org/issues/5047?journal_id=196752011-07-25T23:53:10Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>2011/7/25 Eric Wong <a href="mailto:normalperson@yhbt.net" class="email">normalperson@yhbt.net</a>:</p>
<blockquote>
<p>We can pre-allocate the unlinked_method_entry_list_entry struct<br>
in the METHOD struct and then push it into unlinked_method_entry_list<br>
in bm_free (untested patch below):</p>
</blockquote>
<p>I see! I'll import it if make check passes. Thanks.</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>