[rt-devel] debug info on memory leaks under mod_perl.

Ruslan U. Zakirov cubic at acronis.ru
Tue Oct 21 04:46:08 EDT 2003


Jesse Vincent wrote:
> 
> 
> On Mon, Oct 20, 2003 at 07:41:51PM +0400, Ruslan U. Zakirov wrote:
> 
>>		Hello, RT hackers :)
>>	I want to remember to you that RT leaks.
>>
>>	While my last hacking on RT I've understood that Perl and CPAN 
>>	modules could be buggy too and at first time complain on them. But after 13 
>>hours of fighting with Apache::Leak, B::LexInfo, die 'Test', 
>>Data::Dumper and other similar shit I figured out that it's almost only 
>>RT problem.
>>
>>	The problem is circular references.
>>Good article about it here:
>>http://www.perl.com/pub/a/2002/08/07/proxyobject.html
>>
>>We leak at least one CurrentUser object + all object on which it has 
>>pointer(PrincipalObj, UserObj...) Why? Because of 'user' references on 
>>CurrentUser which have each object inherited from RT::Handle and 
>>RT::Record. And also CurrentObject itself have such pointer. So after 
>>untie of %session perl never call DESTROY on this objects.
>>
>>1) weaken solution is good, but have issues
>>	a) perl should be >5.6.0, but it's not a problem for RT. RT have 
>>	same requirments.
> 
> 
> The following change has been made to RT::Base:
> 
>     sub CurrentUser {
>         my $self = shift;
>     
>         if (@_) {
>             $self->{'user'} = shift;
> |+          Scalar::Util::weaken($self->{'user'}) if (ref($self->{'user'}) &&
> |+                                                      $self->{'user'} == $self );
>         }
> 
> 
> With this in place, RT passes all tests and the following test script
> shows that object destruction is taking place immediately:
> 
Yep. This do Right thing, this is first what I do when was testing 
'weaken' solution. But if we add one string?
> sh-2.05a# more memtest
> #!/usr/bin/perl
> 
> use lib qw(/opt/rt3/lib);
> use RT;
> RT::LoadConfig();
> RT::Init();
> 
> use RT::CurrentUser;
> sub RT::CurrentUser::DESTROY {
>     print "HULK SMASH!\n";
> }
> for (my $i = 1; $i <= 500; $i++) {
>     print "Loading user $user...";
>     my $user = RT::CurrentUser->new('root');
       my $UserObj = $user->UserObj;
> 
> }
> 
> print "Done";
> 
Same with principal object. And bad thing is that we could not isolate 
using of 'weaken' in CurrentUser class. If we do $self->{'UserObj'} 
weaken then when RT lost somewhere pointer on it $self->{'UserObj'} it 
would be undefined and calling it cause another select to DB. :(




More information about the Rt-devel mailing list