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


---
osname= linux
osvers= 2.4.21-1.1931.2.382.entsmp
arch=   i386-linux-thread-multi
cc=     gcc 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
---
Flags:
    category=core
    severity=high
    ack=no
---
I have a dynamic PMC named 'Match' that extends the PerlHash PMC. I
have occasionally been seeing "destroy() not implemented in class
'Match'" on program shutdown. Match does not define destroy(), nor
does it set the active destroy flag. Looking deeper, I find that it's
trying to dispose of a PMC with its ->obj.flags member completely
trashed, and in particular it has an erroneous bit set for the active
destroy flag.

I won't go through all the details of what I looked at (though I'll
post them in my blog eventually), but what's happening is that this
line (from perlhash.pmc's clone() implementation) is corrupting the
flags field:

        ((Hash*)PMC_struct_val(dest))->container = dest;

The problem is that the dest PMC contains a Hash structure in its
struct_val field, but the address of the Hash is only 0x18 bytes
before the address of the PMC itself, and Hashes are 0x40 bytes
each. The offset of the container field within a Hash is 0x20, and the
offset of the flags field within a PMC is 0x04. So assigning to that
container field overwrites the flags field, since 0x18 + 0x04 == 0x20.

It seems like an initialization ordering problem, especially since I
can make the problem go away by changing the clone() method from

    PMC* clone () {
        PMC* dest = pmc_new_noinit(INTERP, SELF->vtable->base_type);
        PObj_custom_mark_SET(dest);
        ((Hash*)PMC_struct_val(dest))->container = dest;
        hash_clone(INTERP, (Hash *)PMC_struct_val(SELF),
                   (Hash**)&PMC_struct_val(dest));
        return dest;
    }

to

    PMC* clone () {
        PMC* dest = pmc_new(INTERP, SELF->vtable->base_type);
        hash_clone(INTERP, (Hash *)PMC_struct_val(SELF),
                   (Hash**)&PMC_struct_val(dest));
        return dest;
    }

But I'm not sure why, and I'm not sure if this is a bug in perlhash's
clone(), or some weird side effect of using dynamic PMCs. (For now,
I'm just reimplementing clone() in my subclass.)

---
Summary of my parrot 0.1.0 configuration:
  configdate='Wed Sep  8 23:20:30 2004'
  Platform:
    osname=linux, archname=i386-linux-thread-multi
    jitcapable=1, jitarchname=i386-linux,
    jitosname=LINUX, jitcpuarch=i386
    execcapable=1
    perl=/usr/bin/perl
  Compiler:
    cc='ccache gcc', ccflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS 
-DDEBUGGING  -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 
-I/usr/include/gdbm -O1',
  Linker and Libraries:
    ld='gcc', ldflags=' -L/usr/local/lib',
    cc_ldflags='',
    libs='-lnsl -ldl -lm -lpthread -lcrypt -lutil -lrt -lgmp'
  Dynamic Linking:
    so='.so', ld_shared='-shared -L/usr/local/lib -fPIC',
    ld_shared_flags=''
  Types:
    iv=long, intvalsize=4, intsize=4, opcode_t=long, opcode_t_size=4,
    ptrsize=4, ptr_alignment=1 byteorder=1234, 
    nv=double, numvalsize=8, doublesize=8

---
Environment:
    HOME    LANG    LANGUAGE    LC_ALL    LD_LIBRARY_PATH    LOGDIR    PATH    SHELL

Reply via email to