On Sunday 22 April 2007 17:57, Alek Storm wrote:
> > That's as far as I've been able to trace however. The tests do pass if I
> > revert the patch. Any ideas?
>
> I think the patch exposed either a GC or SMOP bug. Here's the smallest I
> could get the test case and still have it segfault without gdb's help:
>
> .sub _main :main
> load_bytecode 'library/Test/More.pir'
>
> # import test routines
> .local pmc exports, curr_namespace, test_namespace
> curr_namespace = get_namespace
> test_namespace = get_namespace [ "Test::More" ]
> exports = split " ", "plan ok is isa_ok"
> test_namespace.export_to(curr_namespace, exports)
>
> plan( 9 )
>
> $P0 = new 'SMOP_Attribute'
> isa_ok ($P0, 'SMOP_Attribute')
>
> $S1 = $P0.'name'()
> is ($S1, 'TestClass1', 'test the SMOP_Attribute name method')
>
> $P0 = new 'SMOP_Attribute'
> $S0 = $P0.'type'("TestTypeClass1")
> is ($S0, 'TestTypeClass1', 'test the SMOP_Attribute name method')
>
> $S1 = $P0.'type'()
> is ($S1, 'TestTypeClass1', 'test the SMOP_Attribute name method')
> .end
>
> However, we can make it segfault earlier using gdb, because the problem
> only shows up when a DOD run is triggered. We can test whether the memory
> has been corrupted yet from anywhere in Parrot by issuing this:
>
> call (*interp->arena_base->pmc_pool->more_objects)(interp,
> interp->arena_base->pmc_pool)
>
> If it runs and exits, no problem. If it segfaults, problem. I was able to
> track the cause down to smop_init() in src/pmc/smop_attribute.pmc. Running
> the aforementioned command before the call to mem_sys_allocate_zeroed()
> exits cleanly, but running it afterwards causes a segfault, so
> mem_sys_allocate_zeroed() (and the calloc() inside it) corrupts something.
> That's as far as I can get for now - looking at the code immediately
> preceding the segfault doesn't help any.
>
> The exact same thing happens without the patch, but for some reason the
> test case above doesn't trigger a DOD run on an unpatched parrot, so it
> doesn't show up unless you use gdb. At least it's Not My Fault(TM), but
> this one looks like a doozy to fix. Someone more familiar with the garbage
> collector than I needs to sort this out. Should we start a new ticket?
Nice analysis. I added the run_gc() method to the interpreter a few weeks ago
to help with this sort of thing. Here's a patch to the tests to demonstrate
the bug and a patch to SMOP_Attribute to fix the thing.
Jonathan, can you help us figure out why deleting these lines out of init()
fixes the problem? Are they vestigial?
/* turn on marking of the class_data array */
PObj_data_is_PMC_array_SET(self);
-- c
=== src/pmc/smop_attribute.pmc
==================================================================
--- src/pmc/smop_attribute.pmc (revision 3272)
+++ src/pmc/smop_attribute.pmc (local)
@@ -30,13 +30,13 @@
static void smop_init(Interp *interp, PMC *self) {
SMOP_Attribute *smop = NULL;
- /* turn on marking of the class_data array */
- PObj_data_is_PMC_array_SET(self);
- /* turn on custom destruction since our PMC* array is dynamically allocated */
+
+ /* turn on custom destruction since our PMC* array is dynamically allocated
+ */
PObj_active_destroy_SET(self);
- PMC_data(self) = mem_sys_allocate_zeroed(sizeof(SMOP_Attribute));
- smop = SMOP_attr(self);
+ PMC_data(self) = mem_allocate_zeroed_typed(SMOP_Attribute);
+ smop = SMOP_attr(self);
}
@@ -75,7 +75,10 @@
*/
void destroy() {
+ if (PMC_data(SELF)) {
mem_sys_free(PMC_data(SELF));
+ PMC_data(SELF) = NULL;
+ }
}
=== t/pmc/smop_attribute.t
==================================================================
--- t/pmc/smop_attribute.t (revision 3272)
+++ t/pmc/smop_attribute.t (local)
@@ -6,7 +6,6 @@
t/pmc/smop_attribute.t - test the new SMOP Attribute PMC
-
=head1 SYNOPSIS
% prove t/pmc/smop_attribute.t
@@ -32,48 +31,52 @@
$P0 = new 'SMOP_Attribute'
isa_ok ($P0, 'SMOP_Attribute')
+ # SMOP_Attribute used to cause segfaults when GC ran (RT #42408)
+ $P1 = getinterp
+ $P1.'run_gc'()
- $P0 = new 'SMOP_Attribute'
- $S0 = $P0.'name'("TestClass1")
- is ($S0, 'TestClass1', 'test the SMOP_Attribute name method')
+ $P0 = new 'SMOP_Attribute'
+ $S0 = $P0.'name'("TestClass1")
+ is ($S0, 'TestClass1', 'test the SMOP_Attribute name method')
- $S1 = $P0.'name'()
- is ($S1, 'TestClass1', 'test the SMOP_Attribute name method')
+ $S1 = $P0.'name'()
+ is ($S1, 'TestClass1', 'test the SMOP_Attribute name method')
- $P0 = new 'SMOP_Attribute'
- $S0 = $P0.'type'("TestTypeClass1")
- is ($S0, 'TestTypeClass1', 'test the SMOP_Attribute name method')
- $S1 = $P0.'type'()
- is ($S1, 'TestTypeClass1', 'test the SMOP_Attribute name method')
+ $P0 = new 'SMOP_Attribute'
+ $S0 = $P0.'type'("TestTypeClass1")
+ is ($S0, 'TestTypeClass1', 'test the SMOP_Attribute name method')
+ $S1 = $P0.'type'()
+ is ($S1, 'TestTypeClass1', 'test the SMOP_Attribute name method')
- $P1 = new 'ResizableIntegerArray'
- push $P1, 1
- push $P1, 2
- push $P1, 3
+ $P1 = new 'ResizableIntegerArray'
+ push $P1, 1
+ push $P1, 2
+ push $P1, 3
- $P0 = new 'SMOP_Attribute'
- $P2 = $P0.'class'($P1)
- get_repr $S0, $P2
- is ($S0, '[ 1, 2, 3 ]', 'test the SMOP_Attribute type method with a ResizableIntegerArray' )
- $P3 = $P0.'class'()
- get_repr $S1, $P3
- is ($S1, '[ 1, 2, 3 ]', 'test the SMOP_Attribute type method with a ResizableIntegerArray' )
+ $P0 = new 'SMOP_Attribute'
+ $P2 = $P0.'class'($P1)
+ get_repr $S0, $P2
+ is ($S0, '[ 1, 2, 3 ]', 'test the SMOP_Attribute type method with a ResizableIntegerArray' )
+ $P3 = $P0.'class'()
+ get_repr $S1, $P3
+ is ($S1, '[ 1, 2, 3 ]', 'test the SMOP_Attribute type method with a ResizableIntegerArray' )
- $P1 = new 'FixedIntegerArray'
- set $P1, 3
- $P1[0]= 1
- $P1[1]= 2
- $P1[2]= 3
+ $P1 = new 'FixedIntegerArray'
+ set $P1, 3
+ $P1[0]= 1
+ $P1[1]= 2
+ $P1[2]= 3
- $P0 = new 'SMOP_Attribute'
- $P2 = $P0.'class'($P1)
- get_repr $S0, $P2
- is( $S0, '[ 1, 2, 3 ]', 'test the SMOP_Attribute class method with a FixedIntegerArray' )
- $P3 = $P0.'class'()
- get_repr $S1, $P3
- is( $S1, '[ 1, 2, 3 ]', 'test the SMOP_Attribute class method with a FixedIntegerArray' )
+ $P0 = new 'SMOP_Attribute'
+ $P2 = $P0.'class'($P1)
+ get_repr $S0, $P2
+ is( $S0, '[ 1, 2, 3 ]', 'test the SMOP_Attribute class method with a FixedIntegerArray' )
+ $P3 = $P0.'class'()
+ get_repr $S1, $P3
+ is( $S1, '[ 1, 2, 3 ]', 'test the SMOP_Attribute class method with a FixedIntegerArray' )
+
.end
# Local Variables: