Skip Menu |

This queue is for tickets about the Devel-Cycle CPAN distribution.

Report information
The Basics
Id: 47389
Status: resolved
Priority: 0/
Queue: Devel-Cycle

People
Owner: Nobody in particular
Requestors: rafl [...] debian.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.10
Fixed in: (no value)



Subject: Support closures closing over weak references
Currently, when asked to look for cycles (excluding weak ones) in closures, that close over weak references, cycles are reported, although no non-weak cycles exist. The attached patch adds tests to demonstrate the issue and changes Cycle.pm to make the tests pass.
Subject: 0001-Support-closures-closing-over-weak-references.patch
From 7d90c426d2e872b7ff10b0cfb713d48f1efba39d Mon Sep 17 00:00:00 2001 From: Florian Ragwitz <rafl@debian.org> Date: Sat, 27 Jun 2009 13:38:20 +0200 Subject: [PATCH] Support closures closing over weak references. --- lib/Devel/Cycle.pm | 4 +++- t/Devel-Cycle.t | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/Devel/Cycle.pm b/lib/Devel/Cycle.pm index 91d11ee..0d182f6 100644 --- a/lib/Devel/Cycle.pm +++ b/lib/Devel/Cycle.pm @@ -174,8 +174,10 @@ sub _find_cycle_CODE { my $closed_vars = PadWalker::closed_over( $current ); foreach my $varname ( sort keys %$closed_vars ) { my $value = $closed_vars->{$varname}; + my $isweak = ref $value eq 'REF' && isweak(${ $value }); + next if !$inc_weak_refs && $isweak; _find_cycle_dispatch($value,{%$seenit},$callback,$inc_weak_refs,$complain, - (@report,['CODE',$varname,$current => $value])); + (@report,['CODE',$varname,$current => $value,$inc_weak_refs?$isweak:()])); } } diff --git a/t/Devel-Cycle.t b/t/Devel-Cycle.t index 608c8af..a27d979 100644 --- a/t/Devel-Cycle.t +++ b/t/Devel-Cycle.t @@ -5,7 +5,7 @@ # change 'tests => 1' to 'tests => last_test_to_print'; -use Test::More tests => 12; +use Test::More tests => 13; use Scalar::Util qw(weaken isweak); BEGIN { use_ok('Devel::Cycle') }; @@ -80,10 +80,18 @@ SKIP: my @cyclical = []; $cyclical[0] = \@cyclical; - my $sub = sub { return \@cyclical, \%cyclical; }; + my $foo = \@cyclical; + weaken($foo); + + my $sub = sub { return \@cyclical, \%cyclical, $foo; }; find_cycle($sub,sub {$counter++}); is($counter,3,'found three cycles in $cyclical closure'); + + $counter = 0; + find_weakened_cycle($sub); + find_weakened_cycle($sub,sub {$counter++}); + is($counter,4,'found three cycles (including weakened ones) in closure'); } { -- 1.6.3.1.57.gbd5ef
I fail. The previously attached patch still contained some debugging code and screwed up the test plan if PadWalker wasn't available. The patch I'm attaching now fixes that.
From 4363c5ea9eca827bf4200845f8093f20766d5a65 Mon Sep 17 00:00:00 2001 From: Florian Ragwitz <rafl@debian.org> Date: Sat, 27 Jun 2009 13:38:20 +0200 Subject: [PATCH] Support closures closing over weak references. --- lib/Devel/Cycle.pm | 4 +++- t/Devel-Cycle.t | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/Devel/Cycle.pm b/lib/Devel/Cycle.pm index 91d11ee..0d182f6 100644 --- a/lib/Devel/Cycle.pm +++ b/lib/Devel/Cycle.pm @@ -174,8 +174,10 @@ sub _find_cycle_CODE { my $closed_vars = PadWalker::closed_over( $current ); foreach my $varname ( sort keys %$closed_vars ) { my $value = $closed_vars->{$varname}; + my $isweak = ref $value eq 'REF' && isweak(${ $value }); + next if !$inc_weak_refs && $isweak; _find_cycle_dispatch($value,{%$seenit},$callback,$inc_weak_refs,$complain, - (@report,['CODE',$varname,$current => $value])); + (@report,['CODE',$varname,$current => $value,$inc_weak_refs?$isweak:()])); } } diff --git a/t/Devel-Cycle.t b/t/Devel-Cycle.t index 608c8af..87309d1 100644 --- a/t/Devel-Cycle.t +++ b/t/Devel-Cycle.t @@ -5,7 +5,7 @@ # change 'tests => 1' to 'tests => last_test_to_print'; -use Test::More tests => 12; +use Test::More tests => 13; use Scalar::Util qw(weaken isweak); BEGIN { use_ok('Devel::Cycle') }; @@ -66,7 +66,7 @@ is($counter,0,'found no cycles in reference stringified on purpose to create a f SKIP: { - skip 'These tests require PadWalker 1.0+', 1 + skip 'These tests require PadWalker 1.0+', 2 unless Devel::Cycle::HAVE_PADWALKER; $counter = 0; @@ -80,10 +80,17 @@ SKIP: my @cyclical = []; $cyclical[0] = \@cyclical; - my $sub = sub { return \@cyclical, \%cyclical; }; + my $foo = \@cyclical; + weaken($foo); + + my $sub = sub { return \@cyclical, \%cyclical, $foo; }; find_cycle($sub,sub {$counter++}); is($counter,3,'found three cycles in $cyclical closure'); + + $counter = 0; + find_weakened_cycle($sub,sub {$counter++}); + is($counter,4,'found three cycles (including weakened ones) in closure'); } { -- 1.6.3.1.57.gbd5ef
The above patch fixed my issues, buf after looking at things a little closer, it seems that the problem is actually in _find_cycle_SCALAR. The attached patch fixes that and also makes the test case from the previous patch pass.
From 7e884548d6bb37258cd1b7258ea4fbd5d76b8441 Mon Sep 17 00:00:00 2001 From: Florian Ragwitz <rafl@debian.org> Date: Sat, 27 Jun 2009 16:15:28 +0200 Subject: [PATCH] Fix isweak tests for scalar refs. --- lib/Devel/Cycle.pm | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Devel/Cycle.pm b/lib/Devel/Cycle.pm index 91d11ee..6daf854 100644 --- a/lib/Devel/Cycle.pm +++ b/lib/Devel/Cycle.pm @@ -120,9 +120,9 @@ sub _find_cycle_SCALAR { my $complain = shift; my @report = @_; - return if !$inc_weak_refs && isweak($current); + return if !$inc_weak_refs && isweak($$current); _find_cycle($$current,{%$seenit},$callback,$inc_weak_refs,$complain, - (@report,['SCALAR',undef,$current => $$current,$inc_weak_refs?isweak($current):()])); + (@report,['SCALAR',undef,$current => $$current,$inc_weak_refs?isweak($$current):()])); } sub _find_cycle_ARRAY { -- 1.6.3.1.57.gbd5ef
Any news on this issue? It's is a blocker for a couple of modules I'm working on. Anything I can do to help you getting a fixed release out to CPAN?
The patch is incorporated into version 1.11. Thank you.