From: Peter Rabbitson Date: Thu, 22 Jan 2015 22:27:22 +0000 (+0100) Subject: Fix intermittent failures in the LeakTracer on 5.18+, remove all workarounds X-Git-Tag: v0.08271~12 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=8428e0b6d206d21201046fe454902fcaaa16fe64 Fix intermittent failures in the LeakTracer on 5.18+, remove all workarounds ( cherry-pick of 1a77219a ) ARGH! In the end the issue turned out to be stupid-simple: when PadWalker is called it always returns us a hashref. This hashref is traversed, with its own address recorded as seen. Once processed, the hashref itself is GCed, leaving a stale entry in $seen_refs. Up until 5.18 this was not a problem, likely due to no address reuse. However after 5.18 PadWalker is very happy to return different hashrefs under the same address over and over again. The $seen_refs entry leads to a skip, and the actual contents of the pad are never examined - we've seen this hash already. ARGH! The decisive change is the single line around PadWalker - everything else is cleanup of workarounds for this problem. Conflicts: Changes --- diff --git a/Changes b/Changes index 2e502f3..b73cbe8 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,7 @@ Revision history for DBIx::Class * Misc - Remove warning about potential side effects of RT#79576 (scheduled) + - Fix intermittent failures in the LeakTracer on 5.18+ 0.08270 2014-01-30 21:54 (PST) * Fixes diff --git a/t/52leaks.t b/t/52leaks.t index de3f0b4..8442db5 100644 --- a/t/52leaks.t +++ b/t/52leaks.t @@ -328,9 +328,6 @@ unless (DBICTest::RunMode->is_plain) { ! DBICTest::RunMode->is_plain and ! $ENV{DBICTEST_IN_PERSISTENT_ENV} - and - # FIXME - investigate wtf is going on with 5.18 - ! ( $] > 5.017 and $ENV{DBIC_TRACE_PROFILE} ) ) { # FIXME - ideally we should be able to just populate an alternative diff --git a/t/lib/DBICTest/Util/LeakTracer.pm b/t/lib/DBICTest/Util/LeakTracer.pm index 48ec21d..28e7693 100644 --- a/t/lib/DBICTest/Util/LeakTracer.pm +++ b/t/lib/DBICTest/Util/LeakTracer.pm @@ -11,7 +11,6 @@ use Data::Dumper::Concise; use DBICTest::Util 'stacktrace'; use constant { CV_TRACING => DBIx::Class::Optional::Dependencies->req_ok_for ('test_leaks_heavy'), - SKIP_SCALAR_REFS => ( $] > 5.017 ) ? 1 : 0, }; use base 'Exporter'; @@ -52,10 +51,6 @@ sub populate_weakregistry { for keys %$reg; } - # FIXME/INVESTIGATE - something fishy is going on with refs to plain - # strings, perhaps something to do with the CoW work etc... - return $target if SKIP_SCALAR_REFS and reftype($target) eq 'SCALAR'; - if (! defined $weak_registry->{$refaddr}{weakref}) { $weak_registry->{$refaddr} = { stacktrace => stacktrace(1), @@ -150,7 +145,7 @@ sub visit_refs { elsif (CV_TRACING and $type eq 'CODE') { $visited_cnt += visit_refs({ %$args, refs => [ map { ( !isweak($_) ) ? $_ : () - } scalar PadWalker::closed_over($r) ] }); # scalar due to RT#92269 + } values %{ scalar PadWalker::closed_over($r) } ] }); # scalar due to RT#92269 } 1; } or warn "Could not descend into @{[ _describe_ref($r) ]}: $@\n"; @@ -188,8 +183,6 @@ sub symtable_referenced_addresses { my $refs_per_pkg; - my $dummy_addresslist; - my $seen_refs = {}; visit_namespaces( action => sub { @@ -205,14 +198,7 @@ sub symtable_referenced_addresses { $refs_per_pkg->{$pkg} += visit_refs ( seen_refs => $seen_refs, - # FIXME FIXME FIXME - # This is so damn odd - if we feed a constsub {1} (or in fact almost - # anything other than the actionsub below, any scalarref will show - # up as a leak, trapped by... something... - # Ideally we should be able to const this to sub{1} and just return - # $seen_refs (in fact it is identical to the dummy list at the end of - # a run here). Alas this doesn't seem to work, so punt for now... - action => sub { ++$dummy_addresslist->{ hrefaddr $_[0] } }, + action => sub { 1 }, refs => [ map { my $sym = $_; # *{"$pkg$sym"}{CODE} won't simply work - MRO-cached CVs are invisible there