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-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=1a77219a542c2576b185a61e0787037ecd3fcb9b Fix intermittent failures in the LeakTracer on 5.18+, remove all workarounds 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. --- diff --git a/Changes b/Changes index 40f7c6b..0128cf2 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,7 @@ Revision history for DBIx::Class opener: RT#99503) - Depend on newer Moo, fixing some interoperability issues: http://lists.scsys.co.uk/pipermail/dbix-class/2014-October/011787.html + - Fix intermittent failures in the LeakTracer on 5.18+ 0.082801 2014-10-05 23:55 (UTC) * Known Issues diff --git a/t/52leaks.t b/t/52leaks.t index 95e8bd0..fb8c1c0 100644 --- a/t/52leaks.t +++ b/t/52leaks.t @@ -339,9 +339,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 ad61cd3..1f2caf5 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'; @@ -43,10 +42,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), @@ -145,7 +140,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 @{[ refdesc $r ]}: $@\n"; @@ -183,8 +178,6 @@ sub symtable_referenced_addresses { my $refs_per_pkg; - my $dummy_addresslist; - my $seen_refs = {}; visit_namespaces( action => sub { @@ -200,14 +193,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