From: Peter Rabbitson Date: Tue, 14 Feb 2012 22:05:04 +0000 (+0100) Subject: Add a TODO test for a very elaborate stack leak scenario X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=187ec69a5cabfd5ab651f6e4a6a8b3d59579c94f;p=dbsrgits%2FDBIx-Class-Historic.git Add a TODO test for a very elaborate stack leak scenario --- diff --git a/t/52leaks.t b/t/52leaks.t index ea055a6..aefd001 100644 --- a/t/52leaks.t +++ b/t/52leaks.t @@ -145,6 +145,11 @@ my @compose_ns_classes; cds => [{ title => 'foo cd', year => 1984, + tracks => [ + { title => 't1' }, + { title => 't2' }, + ], + genre => { name => 'mauve' }, }], }); @@ -155,6 +160,15 @@ my @compose_ns_classes; return ($artist, $pg, $pg_wcount); }); + # same for dbh_do + my ($rs_bind_circref, $cond_rowobj) = $schema->storage->dbh_do ( sub { + my $row = $_[0]->schema->resultset('Artist')->new({}); + my $rs = $_[0]->schema->resultset('Artist')->search({ + name => $row, # this is deliberately bogus, see FIXME below! + }); + return ($rs, $row); + }); + is ($pager->next_page, 3, 'There is one more page available'); # based on 66 per 10 pages @@ -222,11 +236,17 @@ my @compose_ns_classes; row_object => $row_obj, + mc_row_object => $mc_row_obj, + result_source => $rs->result_source, result_source_handle => $rs->result_source->handle, pager_explicit_count => $pager_explicit_count, + + leaky_resultset => $rs_bind_circref, + leaky_resultset_cond => $cond_rowobj, + leaky_resultset_member => $rs_bind_circref->next, }; require Storable; @@ -263,8 +283,13 @@ my @compose_ns_classes; $base_collection->{"DBI handle $_"} = $_; } - if ( DBIx::Class::Optional::Dependencies->req_ok_for ('test_leaks') ) { - Test::Memory::Cycle::memory_cycle_ok ($base_collection, 'No cycles in the object collection') + SKIP: { + if ( DBIx::Class::Optional::Dependencies->req_ok_for ('test_leaks') ) { + Test::Memory::Cycle::memory_cycle_ok ($base_collection, 'No cycles in the object collection') + } + else { + skip 'Circular ref test needs ' . DBIx::Class::Optional::Dependencies->req_missing_for ('test_leaks'), 1; + } } for (keys %$base_collection) { @@ -288,8 +313,12 @@ my @compose_ns_classes; sub { shift->result_source }, sub { shift->schema }, sub { shift->clone }, - sub { shift->resultset('Artist') }, + sub { shift->resultset('CD') }, sub { shift->next }, + sub { shift->artist }, + sub { shift->search_related('cds') }, + sub { shift->next }, + sub { shift->search_related('artist') }, sub { shift->result_source }, sub { shift->resultset }, sub { shift->create({ name => 'detached' }) }, @@ -367,6 +396,22 @@ for my $moniker ( keys %{DBICTest::Schema->source_registrations || {}} ) { delete $weak_registry->{DBICTest::Schema->source($moniker)}; } +# FIXME !!! +# There is an actual strong circular reference taking place here, but because +# half of it is in XS no leaktracer sees it, and Devel::FindRef is equally +# stumped when trying to trace the origin. The problem is: +# +# $cond_object --> result_source --> schema --> storage --> $dbh --> {cached_kids} +# ^ / +# \-------- bound value on prepared/cached STH <-----------/ +# +TODO: { + local $TODO = 'Not sure how to fix this yet, an entanglment could be an option'; + my $r = $weak_registry->{'basic leaky_resultset_cond'}{weakref}; + ok(! defined $r, 'We no longer leak!') + or $r->result_source(undef); +} + for my $slot (sort keys %$weak_registry) { ok (! defined $weak_registry->{$slot}{weakref}, "No leaks of $slot") or do {