Subject: | Having autobox loaded makes method calls on already destoryed objects segfault in global destruction |
I have extracted a standalone test case from my work code which was
causing the failure:
use strict;
use warnings;
use Test::More;
is system('/usr/bin/perl', '-e', q{{
package Foo;
use Moose::Autobox;
sub get_bar { $_[0]->{bar} }
sub foo {}
sub DESTROY { $_->[0]->get_bar->bar }
}
{
package Bar;
use Moose::Autobox;
sub get_foo { $_->[0]->{foo} }
sub bar {}
sub DESTROY { $_->[0]->get_foo->foo }
}
my $foo = bless {}, 'Foo';
my $bar = bless { foo => $foo }, 'Bar';
$foo->{bar} = $bar;
exit(0);
}), 0;
done_testing;
The above fails (as the script segfaults), however it works perfectly
without the Moose::Autobox being added (but not used anywhere).
This fails for me on both i386 linux and i386 darwin.
Backtrace from this happening in 'real' code:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff4951d97 in ?? () from /usr/lib/perl5/auto/autobox/autobox.so
(gdb) bt
#0 0x00007ffff4951d97 in ?? () from /usr/lib/perl5/auto/autobox/autobox.so
#1 0x00007ffff495201e in autobox_method_named ()
from /usr/lib/perl5/auto/autobox/autobox.so
#2 0x00007ffff7b1b336 in Perl_runops_standard () from
/usr/lib/libperl.so.5.10
#3 0x00007ffff7ac28cf in Perl_call_sv () from /usr/lib/libperl.so.5.10
#4 0x00007ffff7b2f6d6 in Perl_sv_clear () from /usr/lib/libperl.so.5.10
#5 0x00007ffff7b2fed2 in Perl_sv_free2 () from /usr/lib/libperl.so.5.10
#6 0x00007ffff7b24e22 in ?? () from /usr/lib/libperl.so.5.10
#7 0x00007ffff7b24e81 in Perl_sv_clean_objs () from
/usr/lib/libperl.so.5.10
#8 0x00007ffff7ac4be9 in perl_destruct () from /usr/lib/libperl.so.5.10
#9 0x0000000000400d1c in main ()
(gdb) call (void*)Perl_get_context()
$1 = (void *) 0x603010
(gdb) call (void*)Perl_eval_pv((void*)Perl_get_context(),"eval{require
Carp; Carp::cluck(q{HERE});}", 0)
HERE at (eval 5012) line 1
eval {...} called at (eval 5012) line 1
eval 'eval{require Carp; Carp::cluck(q{HERE});}
;' called at /usr/share/perl5/state51/Logger/Rabbit.pm line 138
state51::Logger::Rabbit::_has_unflushed_messages('state51::Logger::Rabbit=HASH(0x1f22d78)')
called at /usr/share/perl5/state51/Logger/Rabbit.pm line 161
state51::Logger::Rabbit::idle('state51::Logger::Rabbit=HASH(0x1f22d78)')
called at /usr/share/perl5/state51/Logger/Rabbit.pm line 152
state51::Logger::Rabbit::block_till_all_messages_sent('state51::Logger::Rabbit=HASH(0x1f22d78)')
called at /usr/share/perl5/state51/Logger/Rabbit.pm line 148
state51::Logger::Rabbit::DEMOLISH('state51::Logger::Rabbit=HASH(0x1f22d78)',
1) called at /usr/lib/perl5/Moose/Object.pm line 87
Moose::Object::DEMOLISHALL('state51::Logger::Rabbit=HASH(0x1f22d78)', 1)
called at /usr/lib/perl5/Moose/Object.pm line 98
Moose::Object::__ANON__() called at /usr/share/perl5/Try/Tiny.pm
line 76
eval {...} called at /usr/share/perl5/Try/Tiny.pm line 67
Try::Tiny::try('CODE(0x2de1d60)',
'Try::Tiny::Catch=REF(0x3deee20)') called at
/usr/lib/perl5/Moose/Object.pm line 102
Moose::Object::DESTROY('state51::Logger::Rabbit=HASH(0x1f22d78)') called
at (eval 5012) line 0
eval {...} called at (eval 5012) line 0
$2 = (void *) 0x2dd9390
And the snipped of code in question for where I really found the bug:
sub _has_unflushed_messages {
my $self = shift;
my $needs_wait = 0;
foreach my $queue_name ($self->_local_queue_names) {
my $lqueue = $self->_get_local_queue_for($queue_name); # We get
$lqueue = undef here, try to call a method on it below, segfault!
if ($lqueue->depth) {
$needs_wait = 1;
last;
}
}
return $needs_wait;
}
Thanks in advance.