Show quoted text> You mention that "Compress::Zlib::memGunzip takes a reference to $_[0]
> and stores it somewhere in a global". Can't say I'm aware of any global
> that stores a reference to $_[0] in my code. Did you confirm that was
> happening in your investigation, or are you assuming that must be the
> case if you are seeing a leak?
Yes, I confirmed it. See example code below.
Show quoted text> I'm having difficulty reproducing the memory leak you are getting. I ran
> the code below for 30 minutes and didn't see any memory growth in the
> process. Does the code below leak for you?
So it's not a "leak" in that it doesn't grow forever. It's just that
somewhere there is a single reference held to the *last* input to
memGunzip. Normally that's not a problem, but in long lived processes
(eg apache mod_perl handlers) it can be because it can mean an object
lives longer than expected.
Show quoted text> Finally, what version of Perl are you running? What platform
> (linux/Windows etc). Are you running mod_perl? If so, what version?
It's debian linux, perl 5.10.1.
-----
use Compress::Zlib;
# new object
my $f = test->new();
# dummy so we can call memGunzip
my $z = Compress::Zlib::memGzip("");
uz($z, $f);
# undef object reference, should cause test::DESTROY to be called
# straight away because there should be no references left.
# but that's not what happens, object is only destroyed in
# global destruction phase
warn "about to undef last reference";
$f = undef;
warn "after undefing last reference";
sub uz {
# $_[0] == gzip buffer, $_[1] == object reference
my ($zp, $rp) = @_;
# unzip the buffer, don't care about results.
# the bug is that this ends up storing a reference to $zp somewhere
# in a global
Compress::Zlib::memGunzip($zp);
# replace $zp with an object reference. because memGunzip holds a
# reference to $zip somewhere, we now actually have a reference to
# the "test" object held somewhere!
$zp = $rp;
return;
}
# Test object that logs creation/destruction
package test;
sub new {
my $self = bless {}, 'test';
warn "new $self";
return $self;
}
sub DESTROY {
my $self = shift;
warn "destroy $self";
}
-----
What you see:
$ perl /tmp/t.pl
new test=HASH(0x2059f70) at /tmp/t.pl line 41.
about to undef last reference at /tmp/t.pl line 15.
after undefing last reference at /tmp/t.pl line 17.
destroy test=HASH(0x2059f70) at /tmp/t.pl line 47 during global destruction.
Note that the object is only destroyed "during global destruction", not
when the actual last reference is undef'd.
Now if you comment out the call to memGunzip you see:
$ perl /tmp/t.pl
new test=HASH(0x1c25f70) at /tmp/t.pl line 41.
about to undef last reference at /tmp/t.pl line 15.
destroy test=HASH(0x1c25f70) at /tmp/t.pl line 47.
after undefing last reference at /tmp/t.pl line 17.
Which is the correct expected behaviour, the object is destroyed when
the last reference to it is undef'd.