From: Dave Mitchell Date: Sun, 9 Sep 2007 19:51:50 +0000 (+0000) Subject: state variables shouldn't be shared between anon subs X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a74073ad6436c46fca5196ffa4ea01684b55afc4;p=p5sagit%2Fp5-mst-13.2.git state variables shouldn't be shared between anon subs p4raw-id: //depot/perl@31833 --- diff --git a/op.c b/op.c index ca488a2..1ebc84c 100644 --- a/op.c +++ b/op.c @@ -395,6 +395,12 @@ Perl_allocmy(pTHX_ const char *const name) 0, /* not fake */ PL_parser->in_my == KEY_state ); + /* anon sub prototypes contains state vars should always be cloned, + * otherwise the state var would be shared between anon subs */ + + if (PL_parser->in_my == KEY_state && CvANON(PL_compcv)) + CvCLONE_on(PL_compcv); + return off; } diff --git a/t/op/state.t b/t/op/state.t index 6d835c4..c372bf6 100644 --- a/t/op/state.t +++ b/t/op/state.t @@ -10,7 +10,7 @@ BEGIN { use strict; use feature ":5.10"; -plan tests => 117; +plan tests => 119; ok( ! defined state $uninit, q(state vars are undef by default) ); @@ -321,6 +321,18 @@ foreach my $spam (@spam) { is $x, "two", "masked" } +# normally closureless anon subs share a CV and pad. If the anon sub has a +# state var, this would mean that it is shared. Check that this doesn't +# happen + +{ + my @f; + push @f, sub { state $x; ++$x } for 1..2; + $f[0]->() for 1..10; + is $f[0]->(), 11; + is $f[1]->(), 1; +} + foreach my $forbidden () { chomp $forbidden; no strict 'vars';