# New Ticket Created by  Jeff Horwitz 
# Please include the string:  [perl #60030]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=60030 >

a while back in #parrot, i reported a rakudo segfault when calling "use" 
with a multilevel namespace:

./parrot --gc-debug languages/perl6/perl6.pbc -e 'use Foo::Bar'

chromatic was able to reproduce, but debugging proved to be difficult. 
however, i've since been able to narrow it down to a simple pure-PIR test 
case:

===

.sub doit
     .param string s
     $I0 = index s, '::'
     say s
     substr s, $I0, 2, "/"
     say s
     collect
     say s
.end

.sub main :main
     doit('Foo::Bar')
.end

[EMAIL PROTECTED] parrot]$ ./parrot foo.pir
Foo::Bar
Foo/Bar
Segmentation fault

===

i used the "collect" opcode instead of --gc-debug as it helped with debugging.
in any case, the backtrace shows that the string buffer for s is no longer 
valid after collect:

(gdb) p *s
$1 = {cache = {_b = {_bufstart = 0x2b648e5d5ad8, _buflen = 8}, _ptrs = {
       _struct_val = 0x2b648e5d5ad8, _pmc_val = 0x8}, _i = {
       _int_val = 47710885206744, _int_val2 = 8},
     _num_val = 2.357230931332755e-310, _string_val = 0x2b648e5d5ad8},
   flags = 131328,
   strstart = 0x2b648e5d5ad8 <Address 0x2b648e5d5ad8 out of bounds>,
   bufused = 7, strlen = 7, hashval = 0, encoding = 0x60ab10,
   charset = 0x60c250}

after seeing that, i ran it again, setting a watchpoint on s->strstart so 
i could see exactly when it was freed.  the culprit is compact_pool, and i 
was able to get the backtrace from the corresponding free():

Breakpoint 4, 0x00002b87ad29fa90 in free () from /lib64/libc.so.6
(gdb) bt
#0  0x00002b87ad29fa90 in free () from /lib64/libc.so.6
#1  0x00002b87ab8a09bc in mem__internal_free (from=0x2b87ad794010,
     file=0x2b87abaa2dc8 "src/gc/resources.c", line=531) at 
src/gc/memory.c:328
#2  0x00002b87ab9692d5 in compact_pool (interp=0x609080, pool=0x60a4e0)
     at src/gc/resources.c:531
#3  0x00002b87ab969390 in Parrot_go_collect (interp=0x609080)
     at src/gc/resources.c:564
#4  0x00002b87ab8275d9 in Parrot_collect (cur_opcode=0x983700, 
interp=0x609080)
     at src/ops/core.ops:1187
#5  0x00002b87ab8dc65f in runops_slow_core (interp=0x609080, pc=0x983700)
     at src/runops_cores.c:222
#6  0x00002b87ab8adbd4 in runops_int (interp=0x609080, offset=22)
     at src/interpreter.c:937
#7  0x00002b87ab8ae5c3 in runops (interp=0x609080, offs=22)
     at src/inter_run.c:101
#8  0x00002b87ab8ae899 in runops_args (interp=0x609080, sub=0x960f18,
     obj=0x663350, meth_unused=0x0, sig=0x2b87aba9bf03 "vP", 
ap=0x7fffff60ad50)
     at src/inter_run.c:236
#9  0x00002b87ab8aea8b in Parrot_runops_fromc_args (interp=0x609080,
     sub=0x960f18, sig=0x2b87aba9bf03 "vP") at src/inter_run.c:300
#10 0x00002b87ab8943fe in Parrot_runcode (interp=0x609080, argc=1,
     argv=0x7fffff60b048) at src/embed.c:951
#11 0x00002b87aba75568 in imcc_run_pbc (interp=0x609080, obj_file=0,
     output_file=0x0, argc=1, argv=0x7fffff60b048) at 
compilers/imcc/main.c:791
#12 0x00002b87aba75f77 in imcc_run (interp=0x609080,
     sourcefile=0x7fffff60bc42 "foo.pir", argc=1, argv=0x7fffff60b048)
     at compilers/imcc/main.c:1079
#13 0x0000000000400b14 in main (argc=1, argv=0x7fffff60b048) at 
src/main.c:61

i'm not sure if this is compact_pool's fault or if it's just the 
messenger, but obviously the string is still in use and shouldn't be 
freed.  2 other things i noted:

1) this only segfaults if the original string is passed as an argument to 
a subroutine.  for example, this works just fine:

.sub main :main
     $S0 = 'Foo::Bar'
     $I0 = index $S0, '::'
     say $S0
     substr $S0, $I0, 2, "/"
     say $S0
     collect
     say $S0
.end

2) substr has some COW semantics, which may be relevant, but i'm not sure.

-jeff

Reply via email to