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


Run t/pmc/io.t with the GC debugging runcore:

        $ TEST_PROG_ARGS='--runcore=gcdebug' prove t/pmc/io.t

Test 42 should fail:

src/string.c:472: failed assertion '!PObj_on_free_list_TEST(a)'
Backtrace - Obtained 17 stack frames (max trace depth is 32).
  (unknown)
    Parrot_confess
      string_append
        (unknown)
          (unknown)
            PIO_putps
              Parrot_print_sc
                (unknown)
                  (unknown)
                    (unknown)
                      (unknown)
                        Parrot_runops_fromc_args
                          Parrot_runcode
                            imcc_run
                              (unknown)
                                __libc_start_main
                                  (unknown)

Program received signal SIGABRT, Aborted.

This means that it's trying to use a STRING that's on the free list.  Bad 
news:

(gdb) up 4
#4  0xb7ce44f8 in string_append (interp=0x804e008, a=0x81cbb1c, b=0x81f3c7c)
    at src/string.c:472
472         saneify_string(a);
(gdb) l
467
468         /* Is A real? */
469         if (a == NULL || PObj_bufstart(a) == NULL)
470             return string_copy(interp, b);
471
472         saneify_string(a);

With a little bit of tracing (hint: set a breakpoint on new_string_header() 
just before it returns but only if it's returning the pointer involved in 
this expression, then find that breakpoint just before the crash; then do a 
backtrace and see what's allocating that PObj and figure out why it's not 
marking it properly), the culprit is:

PIO_string_write(PARROT_INTERP, NOTNULL(ParrotIOLayer *l), SHIM(ParrotIO *io), 
NOTNULL(STRING *s))
{
    STRING * const old_string = (STRING *)l->self;

    if (!old_string) {
        l->self = s;
        return s->strlen;
    }

***    l->self = string_append(interp, old_string, s);  ***
    return string_length(interp, (STRING *)l->self);
}

The ParrotIOLayer's void pointer now points to a PObj, but what do you want to 
bet that you can't find that that pointer ever gets marked during DOD?  (I 
couldn't.)  We can paper around this bug with:

    dod_register_pmc(interp, l->self);

... just after the string_append() line, but that's a good way to leak STRINGs 
by permanently pinning them in memory (and it's a misuse of the function, at 
least if you go by its name).

However, it does mean that if we keep up this line of thinking, we do need a 
way to identify ParrotIOLayers that hold PObj pointers and mark those 
pointers during DOD.

-- c

Reply via email to