perl5
perl5 copied to clipboard
DESTROY not called on code reference objects
From [email protected]
Created by [email protected]
This might be related to my previous report.
Consider the following program:
#!/opt/perl/bin/perl -w
use strict;
sub new { my ($class, $code) = @_; bless $code => $class; }
DESTROY { print "In DESTROY...\n"; }
my $i = "Hello"; my $exit = main -> new (sub {}); # 1)
__END__
This will not print anything at all, indicating that the DESTROY method isn't called when $exit goes out of scope - not even on program termination.
If we change 1) such that new() is called with a closure, for instance by changing it to:
my $exit = main -> new (sub {$i}); # 1)
DESTROY is called as soon as $exit goes out of scope.
Abigail
Perl Info
Flags:
category=core
severity=high
This perlbug was built using Perl v5.6.0 - Thu Mar 23 19:51:19 EST 2000
It is being executed now by Perl v5.6.0 - Fri Mar 24 17:24:48 EST 2000.
Site configuration information for perl v5.6.0:
Configured by abigail at Fri Mar 24 17:24:48 EST 2000.
Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration:
Platform:
osname=solaris, osvers=2.7, archname=i86pc-solaris-64int
uname='sunos newyork 5.7 generic_106542-07 i86pc i386 i86pc '
config_args='-d -Dprefix=/opt/perl -Uinstallusrbinperl -Doptimize=-g -Duse64bitint'
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=undef d_sfio=undef uselargefiles=define
use64bitint=define use64bitall=undef uselongdouble=undef usesocks=undef
Compiler:
cc='cc', optimize='-g', gccversion=2.95.1 19990816 (release)
cppflags='-DDEBUGGING -fno-strict-aliasing -I/usr/local/include'
ccflags ='-DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
stdchar='char', d_stdstdio=define, usevfork=false
intsize=4, longsize=4, ptrsize=4, doublesize=8
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, usemymalloc=y, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib '
libpth=/usr/local/lib /lib /usr/lib /usr/ccs/lib
libs=-lsocket -lnsl -lgdbm -ldb -ldl -lm -lc -lcrypt -lsec
libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
cccdlflags='-fPIC', lddlflags='-G -L/usr/local/lib'
Locally applied patches:
@INC for perl v5.6.0:
/home/abigail/Perl
/home/abigail/Sybase
/opt/perl/lib/5.6.0/i86pc-solaris-64int
/opt/perl/lib/5.6.0
/opt/perl/lib/site_perl/5.6.0/i86pc-solaris-64int
/opt/perl/lib/site_perl/5.6.0
/opt/perl/lib/site_perl
.
Environment for perl v5.6.0:
HOME=/home/abigail
LANG (unset)
LANGUAGE (unset)
LD_LIBRARY_PATH=/home/abigail/Lib:/usr/local/lib:/usr/lib:/lib:/usr/X11R6/lib
LOGDIR (unset)
PATH=/home/abigail/bin:/usr/local/bin:/usr/local/X11/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/games:/usr/ccs/bin:/usr/openwin/bin:/opt/Acrobat4/bin:/opt/cvs/bin:/opt/perl/bin
PERL5LIB=/home/abigail/Perl:/home/abigail/Sybase
PERLDIR=/opt/perl
PERL_BADLANG (unset)
SHELL=/usr/local/bin/bash
From @schwern
(From perlbug 20000530.008)
Consider the following program:
\#\!/opt/perl/bin/perl \-w use strict; sub new \{ my \($class\, $code\) = @​\_; bless $code => $class; \} DESTROY \{ print "In DESTROY\.\.\.\\n"; \} my $i = "Hello"; my $exit = main \-> new \(sub \{\}\); \# 1\) \_\_END\_\_This will not print anything at all, indicating that the DESTROY method isn't called when $exit goes out of scope - not even on program termination.
If we change 1) such that new() is called with a closure, for instance by changing it to:
my $exit = main \-> new \(sub \{$i\}\); \# 1\)DESTROY is called as soon as $exit goes out of scope.
--
Michael G. Schwern <schwern@pobox.com> http://www.pobox.com/~schwern/ Perl6 Quality Assurance <perl-qa@perl.org> Kwalitee Is Job One I'm exploring my nipples.
From @simoncozens
Created by [email protected]
This works:
{ my $x = new Flow sub {print "Eat this, Hook::Scope\n" }}
package Flow; sub new { my $class = shift; bless {code => $_[0]}, $class } sub DESTROY { my $self = shift; goto &{$self->{code}};}
This doesn't:
{ my $x = new Flow sub {print "Eat this, Hook::Scope\n" }}
package Flow; sub new { my $class = shift; bless $_[0], $class } sub DESTROY { my $self = shift; goto &$self;}
DESTROY is called in the first place but not in the second. This isn't mentioned in the documentation, so either the documentation or the code are wrong...
Perl Info
Flags:
category=core
severity=low
This perlbug was built using Perl v5.7.3 - Fri Jun 14 19:50:26 BST 2002
It is being executed now by Perl v5.6.1 - Fri Jan 11 04:14:18 EST 2002.
Site configuration information for perl v5.6.1:
Configured by bod at Fri Jan 11 04:14:18 EST 2002.
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
Platform:
osname=linux, osvers=2.4.13, archname=i386-linux
uname='linux duende 2.4.13 #1 wed oct 31 19:18:07 est 2001 i686 unknown '
config_args='-Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.6.1 -Darchlib=/usr/lib/perl/5.6.1 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.6.1 -Dsitearch=/usr/local/lib/perl/5.6.1 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Duseshrplib -Dlibperl=libperl.so.5.6.1 -Dd_dosuid -des'
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
Compiler:
cc='cc', ccflags ='-DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2',
cppflags='-DDEBIAN -fno-strict-aliasing -I/usr/local/include'
ccversion='', gccversion='2.95.4 (Debian prerelease)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, usemymalloc=n, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lgdbm -ldb -ldl -lm -lc -lcrypt
perllibs=-ldl -lm -lc -lcrypt
libc=/lib/libc-2.2.4.so, so=so, useshrplib=true, libperl=libperl.so.5.6.1
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'
Locally applied patches:
DEVEL16693
@INC for perl v5.6.1:
/usr/local/lib/perl/5.6.1
/usr/local/share/perl/5.6.1
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.6.1
/usr/share/perl/5.6.1
/usr/local/lib/site_perl
/usr/local/lib/perl/5.6.0
/usr/local/share/perl/5.6.0
.
Environment for perl v5.6.1:
HOME=/home/simon
LANG=en_GB
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/simon/bin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/usr/local/sbin:/usr/sbin:/sbin
PERL_BADLANG (unset)
SHELL=/usr/bin/zsh
From @iabyn
About a year ago, Simon Cozens reported a bug to the effect that
{ my $x = bless sub { }, 'X'; } sub X::DESTROY { print "DESTROYED\n" }
Doesn't call the destructor.
Having looked at it, the reason is that the anon sub isn't a closure (ie doesn't refer to any outer lexicals. Thus, the CV is shared rather than cloned, so its refcnt is >1 when $x is freed.
Turning it into a closure makes it work:
my $y; { my $x = bless sub { $y }, 'X'; } sub X::DESTROY { print "DESTROYED\n" }
Simon mentions that "either the documentation or the code are wrong". Since it would be inefficient to fix, and since closureless anon subs are more common that blessed coderefs (I would speculate), I think it should be documented as a misfeature.
Dave.
-- In England there is a special word which means the last sunshine of the summer. That word is "spring".
From @schwern
On Sun, Aug 17, 2003 at 11:07:15PM +0100, Dave Mitchell wrote:
About a year ago, Simon Cozens reported a bug to the effect that
\{ my $x = bless sub \{ \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}Doesn't call the destructor.
Having looked at it, the reason is that the anon sub isn't a closure (ie doesn't refer to any outer lexicals. Thus, the CV is shared rather than cloned, so its refcnt is >1 when $x is freed.
Turning it into a closure makes it work:
my $y; \{ my $x = bless sub \{ $y \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}Simon mentions that "either the documentation or the code are wrong". Since it would be inefficient to fix, and since closureless anon subs are more common that blessed coderefs (I would speculate), I think it should be documented as a misfeature.
Since it is unnecessarily surprising and inconsistent behavior, and since the reason for it happening is purely for internal and not language reasons, and since we don't want people to start relying on it, and since it would be nice if someone could fix it sometime in the future despite predictions that it will be inefficient to fix, it should be documented not as a feature but as a bug.
Don't document bugs as features. You will hate yourself in the morning.
-- Michael G Schwern schwern@pobox.com http://www.pobox.com/~schwern/ Remember, any tool can be the right tool. -- Red Green
From @ysth
On Sun, Aug 17, 2003 at 05:27:51PM -0700, Michael G Schwern wrote:
On Sun, Aug 17, 2003 at 11:07:15PM +0100, Dave Mitchell wrote:
About a year ago, Simon Cozens reported a bug to the effect that
\{ my $x = bless sub \{ \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}Doesn't call the destructor.
Having looked at it, the reason is that the anon sub isn't a closure (ie doesn't refer to any outer lexicals. Thus, the CV is shared rather than cloned, so its refcnt is >1 when $x is freed.
Turning it into a closure makes it work:
my $y; \{ my $x = bless sub \{ $y \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}Simon mentions that "either the documentation or the code are wrong". Since it would be inefficient to fix, and since closureless anon subs are more common that blessed coderefs (I would speculate), I think it should be documented as a misfeature.
Since it is unnecessarily surprising and inconsistent behavior, and since the reason for it happening is purely for internal and not language reasons, and since we don't want people to start relying on it, and since it would be nice if someone could fix it sometime in the future despite predictions that it will be inefficient to fix, it should be documented not as a feature but as a bug.
Don't document bugs as features. You will hate yourself in the morning.
My initial reaction is to disagree. On second thought, I'm not so sure. According to my initial reaction, sub {} is a kind of constant (*unless* it is a closure). Viewed this way, it's perfectly reasonable that an extra ref be hanging around. But on second thought, if that is the case you shouldn't be able to bless it. Either way, the issue is more than just whether it is destroyed. In this code:
perl -wle'sub cv { sub {} }; my $x = bless cv, 'X'; print ref cv'
either the bless should fail or the second call to cv should get a new CV (thus printing CODE). And the latter sounds better to me (except with something like sub :const { }).
From @simoncozens
Yitzchak Scott-Thoennes:
my $y; \{ my $x = bless sub \{ $y \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}Don't document bugs as features. You will hate yourself in the morning.
My initial reaction is to disagree. On second thought, I'm not so sure.
My initial reaction is that calling a destructor on a sub that happens to be a closure and not on one that doesn't is not just an unexpected special case, but it's surely a bug. Why (and I ask this honestly, not rhetorically) is it supposed to be so hard to fix?
-- User: In 1793 the french king was executed. MegaHAL: HA HA HA! CORRECT. ALTHOUGH, EXECUTED HAS MULTIPLE MEANINGS.
From @iabyn
On Sun, Aug 17, 2003 at 05:27:51PM -0700, Michael G Schwern wrote:
On Sun, Aug 17, 2003 at 11:07:15PM +0100, Dave Mitchell wrote:
Simon mentions that "either the documentation or the code are wrong". Since it would be inefficient to fix, and since closureless anon subs are more common that blessed coderefs (I would speculate), I think it should be documented as a misfeature. [snip] Don't document bugs as features. You will hate yourself in the morning.
Note that I used the word 'misfeature' rather than 'feature'. So I was suggesting to document it as "this may not work, and it may change in future, so don't rely on it".
-- In my day, we used to edit the inodes by hand. With magnets.
From @iabyn
On Mon, Aug 18, 2003 at 05:45:29PM +0100, Simon Cozens wrote:
My initial reaction is that calling a destructor on a sub that happens to be a closure and not on one that doesn't is not just an unexpected special case, but it's surely a bug. Why (and I ask this honestly, not rhetorically) is it supposed to be so hard to fix?
Assuming that we wish to keep the optimisation of sharing non-closure anon CVs, then the problem is that by the time you try to bless the coderef, its already pointing to the shared CV, and you're buggered. By then, you don't really have the option of unsharing it. At least I can't think of a clean way.
-- A walk of a thousand miles begins with a single step... then continues for another 1,999,999 or so.
From [email protected]
On Aug 18, Dave Mitchell wrote:
On Mon, Aug 18, 2003 at 05:45:29PM +0100, Simon Cozens wrote:
My initial reaction is that calling a destructor on a sub that happens to be a closure and not on one that doesn't is not just an unexpected special case, but it's surely a bug. Why (and I ask this honestly, not rhetorically) is it supposed to be so hard to fix?
Assuming that we wish to keep the optimisation of sharing non-closure anon CVs, then the problem is that by the time you try to bless the coderef, its already pointing to the shared CV, and you're buggered. By then, you don't really have the option of unsharing it. At least I can't think of a clean way.
It seems very strange to me to say that an anonymous sub with no private variables is "not a closure." Is not the (shorthand) definition of a closure "a subroutine, associated with all its bindings," even when "all" == 0?
It's great that we have the optimization of not cloning CV's unnecessarily. It's unfortunate that we have the misfeature of Simon's no-DESTRUCT behavior. It's needlessly confusing to say that anonymous subs that have no private bindings aren't closures.
Remember the etymology of "closure." It's from set theory. The empty set is a subset of *all* sets.
- Kurt
From @chipdude
According to Simon Cozens:
Yitzchak Scott-Thoennes:
my $y; \{ my $x = bless sub \{ $y \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}My initial reaction is that calling a destructor on a sub that happens to be a closure and not on one that doesn't is not just an unexpected special case, but it's surely a bug. Why (and I ask this honestly, not rhetorically) is it supposed to be so hard to fix?
Because every value of
$a = sub { print "hi" }
is the same CV. Printing $a will confirm this. The original owner of the CV is the OP tree for the enclosing subroutine (or eval). Until the owning OP tree goes away, the CV's refcount cannot fall to zero. It's very much like
sub hi { print "hi" } $a = \&hi;
The only difference (WRT GC) is that in the \&hi case the original owner is the symbol table, which is visible and can be manipulated from Perl.
In contrast, every value of
my $foo; $b = sub { print $foo }
is a _new_ CV; printing $a will confirm this. Therefore there is no 'original' owner of each new CV; when $b (in this case) lets go, the new CV can be GC'd (and thus DESTROYed). (BTW, there is a parent CV from which all the closure CVs is cloned. This CV is totally hidden from user code. It belongs to the OP tree.) -- Chip Salzenberg - a.k.a. - <chip@pobox.com> "I wanted to play hopscotch with the impenetrable mystery of existence, but he stepped in a wormhole and had to go in early." // MST3K
From @nwc10
On Mon, Aug 18, 2003 at 05:50:16PM -0400, Chip Salzenberg wrote:
According to Simon Cozens:
Yitzchak Scott-Thoennes:
my $y; \{ my $x = bless sub \{ $y \}\, 'X'; \} sub X​::DESTROY \{ print "DESTROYED\\n" \}My initial reaction is that calling a destructor on a sub that happens to be a closure and not on one that doesn't is not just an unexpected special case, but it's surely a bug. Why (and I ask this honestly, not rhetorically) is it supposed to be so hard to fix?
Because every value of
$a = sub { print "hi" }
is the same CV. Printing $a will confirm this. The original owner of
Oh yes. Mmm. Arguably action at a distance:
$ perl -le 'sub foo { return sub {}}; $a = foo; $b = foo; print ref $b; bless $a; print ref $b' CODE main
Nicholas Clark
From @iabyn
On Mon, Aug 18, 2003 at 05:49:16PM -0400, Kurt Starsinic wrote:
It seems very strange to me to say that an anonymous sub withno private variables is "not a closure." Is not the (shorthand) definition of a closure "a subroutine, associated with all its bindings," even when "all" == 0?
It's great that we have the optimization of not cloning CV'sunnecessarily. It's unfortunate that we have the misfeature of Simon's no-DESTRUCT behavior. It's needlessly confusing to say that anonymous subs that have no private bindings aren't closures.
Remember the etymology of "closure\." It's from set theory\.The empty set is a subset of *all* sets.
Well, I've never been very conversant with set theory, so I've never understood the etymology. I've always used it in the sense of something which captures outside lexicals. Otherwise *every* sub is/has a closure, and and the term seems rather to lose its usefulness. Considering that most of the perl documentation still seems to imply that only anon subs can be closures, I had assumed I was already on the liberal wing as regards closure terminology :-)
Dave.
PS - I've been having some sendmail problems this afternoon, so replies to some of my emails may have bounced or been silently queued, due the hostname 'gizmo' leaking into sender addresses. Gack I hate sendmail.
-- Technology is dominated by two types of people: those who understand what they do not manage, and those who manage what they do not understand.
From @chipdude
According to Kurt Starsinic:
Remember the etymology of "closure."
Etymology doesn't define usage, it merely illuminates its origins. Were most everyone to say that X is not Y, then in a linguistic sense it is reasonable to say that X is not Y, no matter the etymology of Y.
And yes that makes me a total descriptivist. But how can a Perl person be otherwise, really? -- Chip Salzenberg - a.k.a. - <chip@pobox.com> "I wanted to play hopscotch with the impenetrable mystery of existence, but he stepped in a wormhole and had to go in early." // MST3K
From @RandalSchwartz
"Kurt" == Kurt Starsinic <kstar@cpan.org> writes:
Kurt> It seems very strange to me to say that an anonymous sub with Kurt> no private variables is "not a closure." Is not the (shorthand) Kurt> definition of a closure "a subroutine, associated with all its Kurt> bindings," even when "all" == 0?
Well, we need a term for that then. I've been adovcating "closure" as when "all > 0", whether named or anonymous.
But if you have a better term (that doesn't take more than three words) for the subroutines that generate a different CV when created as opposed to those that don't, I'm all for it.
If "all subroutines are closures", then the term loses its usefulness within the Perl world.
-- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
From [email protected]
On Monday, August 18, 2003, at 07:12 pm, Dave Mitchell wrote:
Assuming that we wish to keep the optimisation of sharing non-closure anon CVs, then the problem is that by the time you try to bless the coderef, its already pointing to the shared CV, and you're buggered. By then, you don't really have the option of unsharing it. At least I can't think of a clean way.
COW?
Arthur
From @iabyn
On Tue, Aug 19, 2003 at 05:29:09PM +0100, Arthur Bergman wrote:
On Monday, August 18, 2003, at 07:12 pm, Dave Mitchell wrote:
Assuming that we wish to keep the optimisation of sharing non-closure anon CVs, then the problem is that by the time you try to bless the coderef, its already pointing to the shared CV, and you're buggered. By then, you don't really have the option of unsharing it. At least I can't think of a clean way.
COW?
AFAIKT, any COW scheme would break the following:
my $sub = sub { print "hello" }; my $sub2 = $sub; # $sub and $sub1 point to the same CV bless $sub, 'Foo'; # $sub now points to a copy via COW print "not ok\n" unless $sub == $sub2;
-- The optimist believes that he lives in the best of all possible worlds. As does the pessimist.
From [email protected]
On Aug 19, Randal L. Schwartz wrote:
"Kurt" == Kurt Starsinic <kstar@cpan.org> writes: Kurt> It seems very strange to me to say that an anonymous sub with Kurt> no private variables is "not a closure." Is not the (shorthand) Kurt> definition of a closure "a subroutine, associated with all its Kurt> bindings," even when "all" == 0?
Well, we need a term for that then. I've been adovcating "closure" as when "all > 0", whether named or anonymous.
But if you have a better term (that doesn't take more than three words) for the subroutines that generate a different CV when created as opposed to those that don't, I'm all for it.
I suggest that it's a closure when the language supports associating bindings to the subroutine. In Perl, this is always and only the case for anonymous subroutines, whether or not the number of private bindings > 0.
So it seems to me that, in Perl, a named subroutine is never a closure, and an anonymous subroutine is always a closure. The fact that perl optimizes the special case of an anonymous subroutine with 0 private bindings is an implementation detail of interest to a tiny few. This behavior is not guaranteed, and based on Simon's bug, I suspect that it will change.
If "all subroutines are closures", then the term loses its usefulness within the Perl world.
I'm with you 100% there, Randal.
- Kurt
From [email protected]
On Wednesday, August 20, 2003, at 04:31 am, Kurt Starsinic wrote:
So it seems to me that, in Perl, a named subroutine is never a closure, and an anonymous subroutine is always a closure. The fact that perl optimizes the special case of an anonymous subroutine with 0 private bindings is an implementation detail of interest to a tiny few. This behavior is not guaranteed, and based on Simon's bug, I suspect that it will change.
I would say an anonymous subroutine is just that, an anonymous subroutine. It needs outside lexicals to be a closure.
However, I also think this issue is totally irrelevant since only a select few are evil enough to do anything about it, and it is trivial to have a wrapper object around it. Slowing down all anonymous subroutines is just silly. Just document it, close the bug and get on with life.
Arthur
From @iabyn
On Tue, Aug 19, 2003 at 11:31:48PM -0400, Kurt Starsinic wrote:
I suggest that it's a closure when the language supportsassociating bindings to the subroutine. In Perl, this is always and only the case for anonymous subroutines, whether or not the number of private bindings > 0.
So it seems to me that\, in Perl\, a named subroutine is never aclosure, and an anonymous subroutine is always a closure.
But named subs also capture their lexical state at creation time, so I would call them closures too:
X.pm: package X; sub new { my $x = $_[1]; bless \$x } sub DESTROY { print "${$_[0]} destroyed\n" }
my $x1 = X->new('x1'); my $x2 = X->new('x2'); sub f { $x2 } p: #!/usr/bin/perl -w
print "in main\n"; use lib '.'; use X;
gizmo [d]$ ./p x1 destroyed in main x2 destroyed gizmo [d]$
Here, f captures $x2 and so stops it being destroyed at the end of the compilation of X.pm. That is an important behaviour that deserves a label. 'Closure' seems as good a label as any to me.
Similar comments aply to, eg
{ my $c = 0; sub inc { $c++ } sub dec { $c-- } }
-- Never do today what you can put off till tomorrow.
From @iabyn
On Wed, Aug 20, 2003 at 07:12:22PM +0100, Nick Ing-Simmons wrote:
Dave Mitchell <davem@fdgroup.com> writes:
But named subs also capture their lexical state at creation time,
Things get confusing:
sub harry {
my $foo = shift; sub fred { print "$foo\n" } }harry('Ouch'); harry('Weird');
fred();
Run it with -w and you get:
Variable "$foo" will not stay shared at /tmp/p line 6.
Subs capture their lexical environment at creation time. When fred is created, the instance of $foo it captures happens to be the first one. A bit later, 'Ouch' is assigned to this instance. Even later, 'Weird' is assigned to the second instance of $foo, but fred still only sees the first instance.
D.
-- Justice is when you get what you deserve. Law is when you get what you pay for.
From [email protected]
Dave Mitchell <davem@fdgroup.com> writes:
On Tue, Aug 19, 2003 at 11:31:48PM -0400, Kurt Starsinic wrote:
I suggest that it's a closure when the language supportsassociating bindings to the subroutine. In Perl, this is always and only the case for anonymous subroutines, whether or not the number of private bindings > 0.
So it seems to me that\, in Perl\, a named subroutine is never aclosure, and an anonymous subroutine is always a closure.
But named subs also capture their lexical state at creation time,
Things get confusing:
sub harry
{
my $foo = shift;
sub fred { print "$foo\n" }
}
harry('Ouch'); harry('Weird');
fred();
so I would call them closures too:
X.pm: package X; sub new { my $x = $_[1]; bless \$x } sub DESTROY { print "${$_[0]} destroyed\n" }
my $x1 = X->new('x1'); my $x2 = X->new('x2'); sub f { $x2 } p: #!/usr/bin/perl -w
print "in main\n"; use lib '.'; use X;
gizmo [d]$ ./p x1 destroyed in main x2 destroyed gizmo [d]$
Here, f captures $x2 and so stops it being destroyed at the end of the compilation of X.pm. That is an important behaviour that deserves a label. 'Closure' seems as good a label as any to me.
Similar comments aply to, eg
{ my $c = 0; sub inc { $c++ } sub dec { $c-- } }
From [email protected]
Created by [email protected]
perl -wle 'sub DESTROY { print "DESTROY" } my $a = bless sub {}; $a=undef'
The DESTROY never gets called.
Perl Info
Flags:
category=core
severity=low
This perlbug was built using Perl v5.8.5 - Sat Oct 16 01:07:18 CEST 2004
It is being executed now by Perl v5.8.4 - Thu Jun 3 13:28:19 CEST 2004.
Site configuration information for perl v5.8.4:
Configured by ton at Thu Jun 3 13:28:19 CEST 2004.
Summary of my perl5 (revision 5 version 8 subversion 4) configuration:
Platform:
osname=linux, osvers=2.6.5, archname=i686-linux-64int-ld
uname='linux quasar 2.6.5 #8 mon apr 5 05:41:20 cest 2004 i686 gnulinux '
config_args=''
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=define use64bitall=undef uselongdouble=define
usemymalloc=y, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2 -fomit-frame-pointer',
cppflags='-fno-strict-aliasing -I/usr/local/include'
ccversion='', gccversion='3.4.0 20031231 (experimental)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long long', ivsize=8, nvtype='long double', nvsize=12, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
libc=/lib/libc-2.3.2.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.3.2'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'
Locally applied patches:
@INC for perl v5.8.4:
/usr/lib/perl5/5.8.4/i686-linux-64int-ld
/usr/lib/perl5/5.8.4
/usr/lib/perl5/site_perl/5.8.4/i686-linux-64int-ld
/usr/lib/perl5/site_perl/5.8.4
/usr/lib/perl5/site_perl
.
Environment for perl v5.8.4:
HOME=/home/ton
LANG (unset)
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/ton/bin.Linux:/home/ton/bin:/home/ton/bin.SampleSetup:/opt/schily/bin:/usr/local/bin:/usr/local/sbin:/home/oracle/product/9.0.1/bin:/usr/local/ar/bin:/usr/games/bin:/usr/X11R6/bin:/usr/share/bin:/usr/bin:/usr/sbin:/bin:/sbin:.
PERL_BADLANG (unset)
SHELL=/bin/bash
From @iabyn
On Sun, Oct 17, 2004 at 09:10:49PM -0000, perl-5. 8. 0 @ ton. iguana. be wrote:
perl -wle 'sub DESTROY { print "DESTROY" } my $a = bless sub {}; $a=undef'
The DESTROY never gets called.
This has been discussed before. When the anon sub isn't a closure, the code CV is just shared, and so its refcnt never reaches zero.
eg
$ perl -le'push @a, sub {} for 1..5; print $_ for @a' CODE(0x8102b48) CODE(0x8102b48) CODE(0x8102b48) CODE(0x8102b48) CODE(0x8102b48) $ perl -le'my $x;push @a, sub {$x} for 1..5; print $_ for @a' CODE(0x80f6370) CODE(0x8102c08) CODE(0x8102c50) CODE(0x8102c98) CODE(0x8102ce0) $
There doen't seem to be any way of fixing this without impacting the performance of closureless anon sub creation.
Dave.
-- Spock (or Data) is fired from his high-ranking position for not being able to understand the most basic nuances of about one in three sentences that anyone says to him. -- Things That Never Happen in "Star Trek" #19
The RT System itself - Status changed from 'new' to 'open'
From @nwc10
On Mon, Oct 18, 2004 at 05:02:13PM +0100, Dave Mitchell wrote:
On Sun, Oct 17, 2004 at 09:10:49PM -0000, perl-5. 8. 0 @ ton. iguana. be wrote:
perl -wle 'sub DESTROY { print "DESTROY" } my $a = bless sub {}; $a=undef'
The DESTROY never gets called.
This has been discussed before. When the anon sub isn't a closure, the code CV is just shared, and so its refcnt never reaches zero.
There doen't seem to be any way of fixing this without impacting the performance of closureless anon sub creation.
Is it possible to retrospectively change a sub to be shared in the bless operator?
Nicholas Clark
From [email protected]
Nicholas Clark <nick@ccl4.org> wrote
Is it possible to retrospectively change a sub to be shared in the bless operator?
Won't that make the reference point to a new CV? Will it break something like
my $a = sub { ... }; my $b = $a; bless $b; print $a == $b;
Or is there an extra level of indirection?
I certainly think this bug ought to be fixed (and am slightly surprised that I have never tripped over it).
Mike Guy
From @davidnicol
i don't think this matters.
When do you need to catch destruction of an anonymous coderef that is not a closure?
Objects based on coderefs tend to be closures, so they can have their own instance variables.
We could document the shared aspect in the documentation on DESTROY if it's really that troubling
On Mon, 18 Oct 2004 18:40:03 +0100, Mike Guy <mjtg@cam.ac.uk> wrote:
I certainly think this bug ought to be fixed (and am slightly surprised that I have never tripped over it).
Mike Guy
-- David L Nicol transportation infrastructure technology contracting since 2002
From [email protected]
In article <934_64a2041018233558_d94e3@mail.gmail.com>, David Nicol <davidnicol@gmail.com> writes:
i don't think this matters.
When do you need to catch destruction of an anonymous coderef that is not a closure?
Objects based on coderefs tend to be closures, so they can have their own instance variables.
We could document the shared aspect in the documentation on DESTROY if it's really that troubling
The optimization for non-anonymous closures seems sensible, but it should indeed be documented. If I'd known I could easily have worked around the problem (funnily enough I only wanted to bless the sub to check that I did proper cleanup of the object it got stored in, and I solved it by not blessing the sub anymore, but putting a blessed something inside the closure, exactly the kind of thing that would have solved the original problem)
From @davidnicol
Here's i guess what you're asking for, if these lines were added to perltoot.pod it would make DESTROY even scarier. When is destruction deferred, currently? the documentation says it is possible to stack up a bunch of DESTROY calls for later, but doesn't it always happen immediately on refcount clearance, in current perls? The addition below gives an inappropriately detailed example for the tutorial of the not-at-all case and no example for the deferred case. Perldoc does not appear to have a reference page for DESTROY. Maybe a section on "Destroy gotchas" belongs in perltie.pod, near the discussion of UNTIE, and referred to in the introduction to DESTROY in tiescalar, with a "see below."
Imagine adding these lines to perltoot, and wince:
Perl's notion of the right time to call a destructor is not well-defined currently, which is why your destructors should not rely on when they are called. + Generally, DESTROY is called when the reference count on a blessed object drops + to zero. Sometimes this is deferred, and sometimes Perl's optimizer will reuse a + reference, such as to an anonymous subroutine that is not a closure, so the refcount + will never drop to zero, and DESTROY will not be called at all.
On Tue, 19 Oct 2004 08:48:17 +0000 (UTC), Ton Hospel <perl5-porters@ton.iguana.be> wrote:
In article <934_64a2041018233558_d94e3@mail.gmail.com>, David Nicol <davidnicol@gmail.com> writes:
i don't think this matters.
When do you need to catch destruction of an anonymous coderef that is not a closure?
Objects based on coderefs tend to be closures, so they can have their own instance variables.
We could document the shared aspect in the documentation on DESTROY if it's really that troubling
The optimization for non-anonymous closures seems sensible, but it should indeed be documented. If I'd known I could easily have worked around the problem (funnily enough I only wanted to bless the sub to check that I did proper cleanup of the object it got stored in, and I solved it by not blessing the sub anymore, but putting a blessed something inside the closure, exactly the kind of thing that would have solved the original problem)
-- David L Nicol transportation infrastructure technology contracting since 2002