Subject: | Memory loss : the perl memory for a sub {...} never gets freed. |
Date: | Wed, 13 Jun 2018 15:54:46 -0500 |
To: | bug-Tcl [...] rt.cpan.org |
From: | huck <huck [...] finn.com> |
Ah onions
in working on https://rt.cpan.org/Public/Bug/Display.html?id=125472
i discovered another problem: the perl memory for a sub {...} never
gets freed.
Rather than lump it into that problem i decided id make it its own report
if you run the following
use Tcl;
use strict; use warnings;
sub test_use {
my $use=shift;
my $useok=0;
my $bad='';
eval {
$useok =eval $use.';1';
unless ($useok) { $bad=$use; }
};
return $bad;
}
BEGIN {
my $use_bad='';
$use_bad.=test_use ('use Devel::Peek qw( SvREFCNT Dump)');
$use_bad.=test_use ('use Devel::Refcount qw( refcount )');
# $use_bad.=test_use ('use xxx;'); $use_bad.=test_use ('use yxxx;');
if ($use_bad) {
print "1..0 # skip because: not installed $use_bad \n";
exit;
};
}
$| = 1;
print "1..1\n";
my $inter=Tcl->new();
my @queue;
my $sub;
$sub=sub{
return unless (scalar(@queue));
my $line =shift @queue;
return unless (scalar(@queue));
$inter->call('after',300,$sub);
};
my @ctpre=refcts($sub);
print '0 '.join(' ',@ctpre)."\n";
my @ctpost;
for my $run (1..9) {
for my $ii (1..4) {push @queue,'ok '.$ii; }
$inter->call('after',50,$sub);
flush_afters($inter);
if ($Tcl::VERSION eq '1.02') {
# have to kinda cheat and do it by hand in 1.02
# it didnt have code cleaup at all
my $tclname='::perl::'.$sub;
$inter->delete_ref($tclname);
}
@ctpost=refcts($sub);
print "$run ".join(' ',@ctpost)."\n";
}
if ($ctpre[0]==$ctpost[0] && $ctpre[1]==$ctpost[1]) { print "ok 1
- refcts \n";}
else {
unless ($ctpre[0] == $ctpost[0]) { print STDERR "SvREFCNT
$ctpre[0]!=$ctpost[0]\n"; }
unless ($ctpre[1] == $ctpost[1]) { print STDERR "refcount
$ctpre[1]!=$ctpost[1]\n"; }
print "not ok 1 - refcts \n";
}
exit;
sub refcts {
# printf "SvREFCNT=%d refcount=%d\n",SvREFCNT( $_[0] ), refcount( $_[0]) ;
return (SvREFCNT( $_[0] ), refcount( $_[0]));
}
sub flush_afters{
my $inter=shift;
my $ct=0;
while(1) { # wait for afters to finish
my $info0=insure_ptrarray($inter,'after', 'info');
last unless (scalar(@$info0));
$inter->icall('after', 1000, 'set var fafafa');
#print " $inter $ct\n"; $ct++;
$inter->icall('vwait', 'var'); # will wait for 1 seconds
}
}
sub insure_ptrarray{
my $inter=shift;
my $list = $inter->icall(@_);
if (ref($list) ne 'Tcl::List') { # v1.02
$list=[split(' ',$list)];
}
return $list;
}
you find that it just reports an ever increasing refcount value. this is bad.
Even V1.02 is affected.
Ive been working with git (im an old CVSer still) and i think i
should be able to submit a gif-pull to you to fix this.
while it should work without it, adding the following is helpful
git tag -a 1.02 3f5eb527e1ba3b883c2ba197e4bdaf28d940f389 -m "Release 1.02"
Thanks for all you do for us!!!