Hello,

I've been experiencing a segfault when inspecting or calling to_s on a 
Proc object created inside complex data structures under certain 
(seemingly random) conditions. I've been trying unsuccessfully for 3 
weeks to narrow it down to a small test case, but thought I'd mention 
it even without the test case to see if anyone with a better 
understanding of Ruby's internal data structures than I can figure it 
out.

The two projects I've run into the problem both are creating the Proc in 
question inside a fairly complex data structure; one inside a matrix of 
test data for the Ruby binding to the Open Dynamics Engine, and the 
other occurs when printing a progress trace from an Action item 
(wrapper around a Proc) of a parse in an (incomplete) port of Perl's 
Parse::RecDescent.

I've since worked around the problem in Ruby-ODE, but the code for the 
parser project in which this happens can be viewed at:

  http://www.deveiate.org/code/RecDescentParser/

and a snapshot of my working directory can be downloaded via:

  http://www.deveiate.org/cgi/snapshot.rb?snap=RecDescent;compress=gz

All of the instances of the problem that I've seen happen at the call to 
strlen() at line 6726 of eval.c because node->nd_file is a null 
pointer:

  (gdb) run experiments/stage1.rb -v -D 5

I can't for the life of me figure out how to intentionally create a Proc 
whose node's nd_file member is null, however. It happens regularly for 
one test, and then a seemingly innocuous change (eg., adding a printf() 
line above it, running in the debugger or under gdb) will cause it to 
disappear.

Here's one example of a backtrace in gdb (where PWD = the 
RecDescentParser directory):

galendril pts/0 [~/source/ruby/RecDescentParser]
117/579 {0}$ gdb ruby
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you 
are
welcome to change it and/or distribute copies of it under certain 
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for 
details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) run experiments/stage1.rb -v -D 5

[...]

Program received signal SIGSEGV, Segmentation fault.
0x4005c8c6 in proc_to_s (self=1077739304, other=1074546069)
    at eval.c:6736
6736            len += strlen(node->nd_file) + 2 + 
(SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3;
(gdb) bt
#0  0x4005c8c6 in proc_to_s (self=1077739304, other=1074546069)
    at eval.c:6736
#1  0x40056d1a in call_cfunc (func=0x4005c7b8 <proc_to_s>, 
    recv=1077739304, len=0, argc=0, argv=0x0) at eval.c:4498
#2  0x40057319 in rb_call0 (klass=1076390204, recv=1077739304, 
    id=3113, oid=3113, argc=0, argv=0x0, body=0x40286810, nosuper=1)
    at eval.c:4629
#3  0x40057b62 in rb_call (klass=1076390204, recv=1077739304, 
    mid=3113, argc=0, argv=0x0, scope=1) at eval.c:4845
#4  0x40057ddc in rb_funcall (recv=1077739304, mid=3113, n=0)
    at eval.c:4918
#5  0x40081780 in rb_obj_inspect (obj=1077739304) at object.c:273
#6  0x40056d1a in call_cfunc (func=0x400814c0 <rb_obj_inspect>, 
    recv=1077739304, len=0, argc=0, argv=0x0) at eval.c:4498
#7  0x40057319 in rb_call0 (klass=1076448404, recv=1077739304, 
    id=3121, oid=3121, argc=0, argv=0x0, body=0x402947f8, nosuper=0)
    at eval.c:4629
#8  0x40057b62 in rb_call (klass=1076448404, recv=1077739304, 
    mid=3121, argc=0, argv=0x0, scope=1) at eval.c:4845
#9  0x40057ddc in rb_funcall (recv=1077739304, mid=3121, n=0)
    at eval.c:4918
#10 0x400812f9 in rb_inspect (obj=1077739304) at object.c:207
#11 0x400813f5 in inspect_i (id=13954, value=1077739304, 
    str=1077013336) at object.c:232
#12 0x400b438b in st_foreach (table=0x826f3d0, 
    func=0x4008130c <inspect_i>, arg=0x4031eb58 "\a") at st.c:494
#13 0x4008146e in inspect_obj (obj=1077743024, str=1077013336)
    at object.c:243
#14 0x4003d54c in inspect_call (arg=0xbfff0314) at array.c:916
#15 0x40056391 in rb_ensure (b_proc=0x4003d528 <inspect_call>, 
    data1=3221160724, e_proc=0x4003d558 <inspect_ensure>, 
    data2=1077743024) at eval.c:4312
#16 0x4003d63e in rb_protect_inspect (func=0x40081440 <inspect_obj>, 
    obj=1077743024, arg=1077013336) at array.c:953
#17 0x40081758 in rb_obj_inspect (obj=1077743024) at object.c:271
#18 0x40056d1a in call_cfunc (func=0x400814c0 <rb_obj_inspect>, 
    recv=1077743024, len=0, argc=0, argv=0x0) at eval.c:4498
#19 0x40057319 in rb_call0 (klass=1076448404, recv=1077743024, 
    id=3121, oid=3121, argc=0, argv=0x0, body=0x402947f8, nosuper=0)
    at eval.c:4629
#20 0x40057b62 in rb_call (klass=1076448404, recv=1077743024, 
    mid=3121, argc=0, argv=0x0, scope=1) at eval.c:4845
#21 0x40057ddc in rb_funcall (recv=1077743024, mid=3121, n=0)
    at eval.c:4918
#22 0x400812f9 in rb_inspect (obj=1077743024) at object.c:207
#23 0x4003d73b in inspect_ary (ary=1077503924) at array.c:977
#24 0x4003d54c in inspect_call (arg=0xbfff0740) at array.c:916
#25 0x40056391 in rb_ensure (b_proc=0x4003d528 <inspect_call>, 
    data1=3221161792, e_proc=0x4003d558 <inspect_ensure>, 
    data2=1077503924) at eval.c:4312
#26 0x4003d63e in rb_protect_inspect (func=0x4003d6c0 <inspect_ary>, 
    obj=1077503924, arg=0) at array.c:953
#27 0x4003d812 in rb_ary_inspect (ary=1077503924) at array.c:993
#28 0x40056d1a in call_cfunc (func=0x4003d7c8 <rb_ary_inspect>, 
    recv=1077503924, len=0, argc=0, argv=0x0) at eval.c:4498
#29 0x40057319 in rb_call0 (klass=1076418684, recv=1077503924, 
    id=3121, oid=3121, argc=0, argv=0x0, body=0x4028d7a0, nosuper=1)
    at eval.c:4629

[...]

#153 0x4004d46b in eval_node (self=1076443644, node=0x40285528)
    at eval.c:1145
#154 0x4004d994 in ruby_exec () at eval.c:1290
#155 0x4004da25 in ruby_run () at eval.c:1310
#156 0x8048672 in main (argc=5, argv=0xbffff294, envp=0xbffff2ac)
    at main.c:50
#157 0x4015856d in __libc_start_main (main=0x8048644 <main>, argc=5, 
    ubp_av=0xbffff294, init=0x80484b0 <_init>, 
    fini=0x80486c0 <_fini>, rtld_fini=0x4000aa14 <_dl_fini>, 
    stack_end=0xbffff28c) at ../sysdeps/generic/libc-start.c:129

(gdb) c
Continuing.
lib/recdescent/parser/SimpleItems.rb:247: [BUG] Segmentation fault
ruby 1.8.0 (2002-12-29) [i686-linux]


The ruby code from where this happens is:

  parseState.debugMsg 4, "Repetition matched. Rvals = %s" %  
    rvals.inspect

...where rvals is an Array which contains an object with a Proc as one 
of its instance variables. It also happens sometimes from direct calls 
to Proc#to_s.

My ruby is:

  ruby 1.8.0 (2002-12-29) [i686-linux]

configured with:

  ./configure -q --prefix=/usr --enable-shared --enable-frame-address


Any suggestions about how to help figure this out welcomed.

-- 
Michael Granger <ged / FaerieMUD.org>
Rubymage, Believer, Architect
The FaerieMUD Consortium <http://www.FaerieMUD.org/>