Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Missing reference and memory leak

by glasswalk3r (Pilgrim)
on Oct 04, 2013 at 18:08 UTC ( #1056906=perlquestion: print w/ replies, xml ) Need Help??
glasswalk3r has asked for the wisdom of the Perl Monks concerning the following question:

Greetings monks,

I found that my program (which is supposed to run for a long time) is leaking memory at each iteration it executes. I have already checked that by monitoring memory consumption by the process, by using Devel::Gladiator and Devel::FindRef.

Devel::Gladiator shows that my FSA::Rules instances are not being terminated as expected. I also added debug messages to the DESTROY method with syswrite to check if the object's are being terminated in the expected order. Here is what I got by running my test script:

$ perl t/DaemonHeavyLeak.t ListParser is gone End of program daemon is gone FSA::Rules=HASH(0x2faeea8) [refcount 2] is +- referenced by REF(0x2fa6ea8) [refcount 1], which is | not found anywhere I looked :( +- referenced by REF(0x27a1578) [refcount 1], which is the lexical '$self' in CODE(0x27978b8) [refcount 4], which is the global &FSA::Rules::DESTROY. FSA::Rules=HASH(0x2faeea8) [refcount 1] is referenced by REF(0x2fa6ea8) [refcount 1], which is not found anywhere I looked :( FSA::Rules is dead FSA::Rules=HASH(0x2e7a198) [refcount 2] is +- referenced by REF(0x2e7a768) [refcount 1], which is | not found anywhere I looked :( +- referenced by REF(0x27a1578) [refcount 1], which is the lexical '$self' in CODE(0x27978b8) [refcount 4], which is the global &FSA::Rules::DESTROY. FSA::Rules=HASH(0x2e7a198) [refcount 1] is referenced by REF(0x2e7a768) [refcount 1], which is not found anywhere I looked :( FSA::Rules is dead

Here is the testing code that I used:

use warnings; use strict; use Siebel::Srvrmgr::Daemon::Heavy; use Cwd; use File::Spec; use Scalar::Util qw(weaken); my $repeat = 3; my $daemon = Siebel::Srvrmgr::Daemon::Heavy->new( { gateway => 'whatever', enterprise => 'whatever', user => 'whatever', password => 'whatever', server => 'whatever', bin => File::Spec->catfile( getcwd(), 'srvrmgr-moc +k.pl' ), use_perl => 1, is_infinite => 0, timeout => 0, commands => [ Siebel::Srvrmgr::Daemon::Command->new( command => 'list comp', action => 'Dummy' ) ] } ); for ( 1 .. $repeat ) { $daemon->run(); } syswrite STDOUT, "End of program\n";

And the modified DESTROY of FSA::Rules:

sub DESTROY { my $self = shift; use Devel::FindRef; use Scalar::Util qw(weaken); syswrite STDOUT, Devel::FindRef::track $self; weaken($self); delete $machines{+shift}; syswrite STDOUT, Devel::FindRef::track $self; syswrite STDOUT, "FSA::Rules is dead\n" }

The correct order of messages of termination should be:

  1. FSA:Rules
  2. ListParser
  3. The program itself
  4. daemon

The thing is, at each execution of run(), a new FSA::Object is kept in memory unit program termination.

Besides, the message from Devel::FindRef:

+- referenced by REF(0x2e7a768) [refcount 1], which is | not found anywhere I looked :(

leaves me without hope to find what is happening.

There is anything else that I could do to detect where in the code this reference is being kept?

Alceu Rodrigues de Freitas Junior
---------------------------------
"You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

Comment on Missing reference and memory leak
Select or Download Code
Re: Missing reference and memory leak
by chromatic (Archbishop) on Oct 04, 2013 at 18:40 UTC

    This looks suspicious:

            delete $machines{+shift};

    Do you mean $self instead of +shift? That may not solve the original problem, but it might help you debug further.

      In fact, the code:

      delete $machines{+shift};

      is from the original author of FSA::Rules. I just added the debug messages and the Devel::FindRef.

      You were right about your guess: I moved the usage of Devel::FindRef to the scope of ListParser class and could get the message:

      FSA::Rules=HASH(0x31cc818) [refcount 13] is +- referenced by REF(0x31d8740) [refcount 1], which is | the member 'machine' of HASH(0x31cc788) [refcount 1],

      Later, in the DESTROY, Devel::FindRef gave me the same HASH address.

      After a fair amount of time checking the code of FSA::Rules, I got this (I pasted only the interesting parts):

      I created a new method to loop over %machines and %states and setting the references to the FSA::Rules object to undef. and invoked it at the end of parse method from ListParser.

      After that, I could finally get the object termination in the moment that I want:

      Thanks!

      Alceu Rodrigues de Freitas Junior
      ---------------------------------
      "You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

        Am I understanding that your original usage was based on code examples from the module's POD? If those examples contribute to leaky code, you might do the community a favor by submitting a bug report for the module's POD.


        Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1056906]
Approved by aitap
Front-paged by aitap
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2014-09-20 19:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (160 votes), past polls