X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Flib%2FDBICTest%2FUtil%2FLeakTracer.pm;h=b36843edd37f18dbe13b04c258493249295fabdb;hb=dc71574729e5f45defc433ca2e11b7c2377eaf95;hp=447d0ec10767692cfbce8acea59617d58ea0fbcb;hpb=5e5823f108f61bd7afa01c180102bc42bad3834b;p=dbsrgits%2FDBIx-Class.git diff --git a/t/lib/DBICTest/Util/LeakTracer.pm b/t/lib/DBICTest/Util/LeakTracer.pm index 447d0ec..b36843e 100644 --- a/t/lib/DBICTest/Util/LeakTracer.pm +++ b/t/lib/DBICTest/Util/LeakTracer.pm @@ -3,14 +3,20 @@ package DBICTest::Util::LeakTracer; use warnings; use strict; +use ANFANG; use Carp; use Scalar::Util qw(isweak weaken blessed reftype); -use DBIx::Class::_Util qw(refcount hrefaddr refdesc); -use DBIx::Class::Optional::Dependencies; -use Data::Dumper::Concise; -use DBICTest::Util qw( stacktrace visit_namespaces ); +use DBIx::Class::_Util qw(refcount hrefaddr refdesc dump_value visit_namespaces); +use DBICTest::RunMode; +use DBICTest::Util 'stacktrace'; use constant { - CV_TRACING => !DBICTest::RunMode->is_plain && DBIx::Class::Optional::Dependencies->req_ok_for ('test_leaks_heavy'), + CV_TRACING => !!( + !DBICTest::RunMode->is_plain + && + require DBIx::Class::Optional::Dependencies + && + DBIx::Class::Optional::Dependencies->req_ok_for ('test_leaks_heavy') + ), }; use base 'Exporter'; @@ -42,17 +48,23 @@ sub populate_weakregistry { for keys %$reg; } + return $target if ( + DBIx::Class::_ENV_::BROKEN_WEAK_SCALARREF_VALUES + and + ref $target eq 'SCALAR' + ); + if (! defined $weak_registry->{$refaddr}{weakref}) { + + # replace slot entirely $weak_registry->{$refaddr} = { stacktrace => stacktrace(1), weakref => $target, }; - # on perl < 5.8.3 sometimes a weaken can throw (can't find RT) - # so guard against that unlikely event - local $@; - eval { weaken( $weak_registry->{$refaddr}{weakref} ); $refs_traced++ } - or delete $weak_registry->{$refaddr}; + weaken( $weak_registry->{$refaddr}{weakref} ); + + $refs_traced++; } my $desc = refdesc $target; @@ -66,7 +78,7 @@ sub populate_weakregistry { } # Regenerate the slots names on a thread spawn -sub CLONE { +sub DBICTest::__LeakTracer_iThreads_handler__::CLONE { my @individual_regs = grep { scalar keys %{$_||{}} } values %reg_of_regs; %reg_of_regs = (); @@ -90,6 +102,11 @@ sub CLONE { $reg->{$new_addr} = $slot_info; } } + + # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage + # collected before leaving this scope. Depending on the code above, this + # may very well be just a preventive measure guarding future modifications + undef; } sub visit_refs { @@ -122,6 +139,7 @@ sub visit_refs { my $type = reftype $r; + local $SIG{__DIE__} if $SIG{__DIE__}; local $@; eval { if ($type eq 'HASH') { @@ -207,7 +225,7 @@ sub assert_empty_weakregistry { # in case we hooked bless any extra object creation will wreak # havoc during the assert phase local *CORE::GLOBAL::bless; - *CORE::GLOBAL::bless = sub { CORE::bless( $_[0], (@_ > 1) ? $_[1] : caller() ) }; + *CORE::GLOBAL::bless = sub { CORE::bless( $_[0], (@_ > 1) ? $_[1] : CORE::caller() ) }; croak 'Expecting a registry hashref' unless ref $weak_registry eq 'HASH'; @@ -232,13 +250,13 @@ sub assert_empty_weakregistry { # the symtable walk is very expensive # if we are $quiet (running in an END block) we do not really need to be - # that thorough - can get by with only %Sub::Quote::QUOTED + # that thorough - can get by with our own registry delete $weak_registry->{$_} for $quiet ? do { my $refs = {}; visit_refs ( # only look at the closed over stuffs - refs => [ grep { length ref $_ } map { values %{$_->[2]} } grep { ref $_ eq 'ARRAY' } values %Sub::Quote::QUOTED ], + refs => [ values %DBIx::Class::_Util::refs_closed_over_by_quote_sub_installed_crefs ], seen_refs => $refs, action => sub { 1 }, ); @@ -266,7 +284,7 @@ sub assert_empty_weakregistry { ref($weak_registry->{$addr}{weakref}) eq 'CODE' and B::svref_2object($weak_registry->{$addr}{weakref})->XSUB - ) ? '__XSUB__' : Dumper( $weak_registry->{$addr}{weakref} ) + ) ? '__XSUB__' : dump_value $weak_registry->{$addr}{weakref} ; }; @@ -299,7 +317,7 @@ sub assert_empty_weakregistry { } if (! $quiet and !$leaks_found and ! $tb->in_todo) { - $tb->ok(1, sprintf "No leaks found at %s line %d", (caller())[1,2] ); + $tb->ok(1, sprintf "No leaks found at %s line %d", (CORE::caller())[1,2] ); } }