Odd random segfaults in 1.9.2dev with gem method

Got some segfault errors when trying to run rake test for rails.

Minimal code example to reproduce is: ruby -e ‘gem “rake”’

the odd thing is that these segfaults are not 100% reproducible,
sometimes it works as expected:

-----8<----------
$ ruby -e ‘gem “rake”’
internal:gem_prelude:187:in push_gem_version_on_load_path': Could not find RubyGem rake (>= 0) (Gem::LoadError) from /home/nlugovoi/lib/ruby/1.9.1/rubygems/defaults.rb:0:inrescue in default_exec_format’
from -e:1:in `’
-----8<----------

But sometimes it just fails:

-----8<----------
$ ruby -e ‘gem “rake”’
/home/nlugovoi/lib/ruby/1.9.1/rubygems.rb:1093: [BUG] Segmentation fault
ruby 1.9.2dev (2009-09-04 trunk 24743) [i686-linux]

– control frame ----------
c:0012 p:---- s:0043 b:0043 l:000042 d:000042 CFUNC :require
c:0011 p:0209 s:0039 b:0039 l:000038 d:000038 TOP
/home/nlugovoi/lib/ruby/1.9.1/rubygems.rb:1093
c:0010 p:---- s:0036 b:0036 l:000035 d:000035 FINISH
c:0009 p:---- s:0034 b:0034 l:000033 d:000033 CFUNC :require
c:0008 p:0092 s:0030 b:0030 l:000029 d:000029 METHOD
internal:gem_prelude:159
c:0007 p:0017 s:0027 b:0027 l:000026 d:000026 METHOD
internal:gem_prelude:279
c:0006 p:---- s:0023 b:0023 l:000022 d:000022 FINISH
c:0005 p:0043 s:0021 b:0020 l:000019 d:000019 METHOD
internal:gem_prelude:187
Segmentation fault
-----8<----------

From gdb I get:

-----8<----------
#0 0x0813a387 in vm_backtrace_push (arg=0xbfffa0ec, file=0,
line_no=0, name=0) at vm.c:755
#1 0x0813a2db in vm_backtrace_each (th=0x81faa98, lev=-2,
iter=0x813a363 <vm_backtrace_push>, arg=0xbfffa0ec) at vm.c:733
#2 0x0813a44c in vm_backtrace (th=0x81faa98, lev=-1) at vm.c:768
#3 0x08138ac7 in rb_make_backtrace () at vm_eval.c:1426
#4 0x0805b8ac in rb_longjmp (tag=6, mesg=140818900) at eval.c:363
#5 0x0805bb5e in rb_exc_raise (mesg=140818900) at eval.c:419
#6 0x0816d319 in rb_raise (exc=136482940, fmt=0x81a3676 “no such file
to load – %s”) at error.c:1132
#7 0x0816f580 in load_failed (fname=140824860) at load.c:532

754 bt = rb_enc_sprintf(rb_enc_compatible(file, name), “%s:%d:in
`%s’”,
755 RSTRING_PTR(file), line_no,
RSTRING_PTR(name));
(gdb) up
#1 0x0813a2db in vm_backtrace_each (th=0x81faa98, lev=-2,
iter=0x813a363 <vm_backtrace_push>, arg=0xbfffa0ec) at vm.c:733
733 if ((*iter)(arg, file, line_no, iseq->name))
break;
(gdb) l
728 if (cfp->pc != 0) {
729 rb_iseq_t *iseq = cfp->iseq;
730
731 line_no = rb_vm_get_sourceline(cfp);
732 file = iseq->filename;
733 if ((*iter)(arg, file, line_no, iseq->name))
break;
734 }
-----8<----------

My theory is that when method Kernel#gem, originally defined in
gem_prelude, is redefined/discarded in rubygems.rb, then original
iseq for method becomes orphaned and is freed by garbage collector.
But it is still referenced from control frame, so segfault.

I tried quick&dirty patch to explicitly mark iseq objects, not sure
if it is correct way:
-----8<----------
— a/vm.c
+++ b/vm.c
@@ -1415,7 +1415,21 @@ static int
vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t
dummy)
{
VALUE thval = (VALUE)key;

  • rb_thread_t *th;
  • rb_control_frame_t *cfp;
  • GetThreadPtr(thval, th);
  • cfp = th->cfp;
  • while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
  •   if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
    
  •           rb_gc_mark(cfp->iseq->self);
    
  •   }
    
  •   cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
    
  • }
  • rb_gc_mark(thval);
  • return ST_CONTINUE;
    }
    -----8<----------
    and that seemed to eliminate such segfaults

Any other explanations or fixes?

yes, i also get this error

minimum example

gem(‘twitter4r’, ‘>=0.2.0’)

gives me

/usr/local/lib/ruby/1.9.1/rubygems.rb:1093: [BUG] Segmentation fault
ruby 1.9.2dev (2009-09-03 trunk 24741) [i686-linux]

– control frame ----------
c:0010 p:---- s:0036 b:0036 l:000035 d:000035 CFUNC :require
c:0009 p:0209 s:0032 b:0032 l:000031 d:000031 TOP
/usr/local/lib/ruby/1.9.1/rubygems.rb:1093
c:0008 p:---- s:0029 b:0029 l:000028 d:000028 FINISH
c:0007 p:---- s:0027 b:0027 l:000026 d:000026 CFUNC :require
c:0006 p:0092 s:0023 b:0023 l:000022 d:000022 METHOD
internal:gem_prelude:159
c:0005 p:0314 s:0020 b:0020 l:000019 d:000019 METHOD
internal:gem_prelude:213
Segmentation fault