hdjoe has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a problem with a memory leak in a perl program that is using the Net::Daemon module.

I copied the Calculator example from the CPAN site and used it as the skeleton for my own program.

I am running my program on a Windows 2000 system and every time a remote system connects to it I can see the memory for the perl process increase about 4K. It acts like maybe the thread that gets started to access the new connection doesn’t get cleaned up for some reason.

What the program does is sit on one of my build machines and allows me to collect information from the machine to get status about builds and to allow me to start a build remotely.

I was wondering if I am doing something wrong since this is my first server/client program.

Time: [Mon Dec 8 16:10:32 2008] Mon Dec 8 16:10:32 2008 : Starti +ng Monitor client Parent session Time: [Mon Dec 8 16:10:51 2008] Client: Recieved input of <sx_4.9. +2.0> <Get_Status> Time: [Mon Dec 8 16:10:51 2008] Check_Build branch:<sx_4.9.2.0> c +:\buildscripts\sx_4.9.2.0\inProgress Time: [Mon Dec 8 16:11:08 2008] Get_Status: SX_4.9.2.0.124.000 5,2 +30,792,704 Passed Thu Dec 4 21:35:48 2008 Time: [Mon Dec 8 16:11:08 2008] Client: Closing Socket and shuttin +g down? Time: [Mon Dec 8 16:11:08 2008] Client: Recieved input of <sx_4.9. +1.0> <Get_Status> Time: [Mon Dec 8 16:11:08 2008] Check_Build branch:<sx_4.9.1.0> c +:\buildscripts\sx_4.9.1.0\inProgress Time: [Mon Dec 8 16:11:19 2008] Get_Status: SX_4.9.1.0.097.000 5,2 +30,268,416 Passed Fri Nov 7 14:28:47 2008 Time: [Mon Dec 8 16:11:19 2008] Client: Closing Socket and shuttin +g down? Time: [Mon Dec 8 16:12:19 2008] Client: Recieved input of <sx_4.9. +2.0> <Get_Status> Time: [Mon Dec 8 16:12:19 2008] Check_Build branch:<sx_4.9.2.0> c +:\buildscripts\sx_4.9.2.0\inProgress Time: [Mon Dec 8 16:12:31 2008] Get_Status: SX_4.9.2.0.124.000 5,2 +18,193,408 Passed Thu Dec 4 21:35:48 2008 Time: [Mon Dec 8 16:12:31 2008] Client: Closing Socket and shuttin +g down? Time: [Mon Dec 8 16:12:31 2008] Check_Build branch:<sx_4.9.1.0> c +:\buildscripts\sx_4.9.1.0\inProgress sub Run ($) { my $DEBUG_LOG="c:\\buildscripts\\Monitor\\Client_log.txt"; my($self) = @_; my($line, $sock); my($result); my($rc); my($command); $sock = $self->{'socket'}; if ($self->{'debug'} eq 'ON') { open(DEBUG,">$DEBUG_LOG"); } while(1) { if (!defined($line = $sock->getline())) { if ($sock->error()) { $self->Error("Client connection error %s",$sock->err +or()); } eventLog("Client: Closing Socket and shutting down?"); $sock->close(); return; } $line =~ s/\s+$//; # Remove CRLF ($L_BRANCH,$command)=split(" ",$line); $U_BRANCH=uc($L_BRANCH); eventLog("Client: Recieved input of <$L_BRANCH> <$command>"); SWITCH: { if ( $command eq "Run_Build") { $result=Run_Build(); + last SWITCH; } if ( $command eq "Check_Build") { $result=Check_Build(); + last SWITCH; } if ( $command eq "Get_Status") { $result=Get_Status(); + last SWITCH; } if ( $command eq "Get_Label") { $result=Get_Last_Build_Lab +el(); last SWITCH; } if ( $command eq "Help") { $result=$help_statement; + last SWITCH; } $result="ERROR: Input did not match expected protocol <$comm +and>\n"; } $rc = printf $sock ("%s\n", $result); if (!$rc) { $self->Error("Client connection error %s", $sock->error()); $sock->close(); return; } } } sub new ($$;$) { my($class, $attr, $args) = @_; my($self) = $class->SUPER::new($attr, $args); if ($self->{'parent'}) { # Called via Clone() $self->{'debug'} = $self->{'parent'}->{'debug'}; } else { # Initial call if ($self->{'options'} && $self->{'options'}->{'debug'}) { $self->{'debug'} = $self->{'options'}->{'debug'} } } if (!$self->{'debug'}) { $self->{'debug'} = 'ON'; } $self; }

Replies are listed 'Best First'.
Re: memory leak Issue
by BrowserUk (Patriarch) on Dec 09, 2008 at 02:09 UTC
    I was wondering if I am doing something wrong

    There really is no way to tell from the sub selection of the code you've chosen to post.

    You mention "thread", but there is nothing to indicate whether you mean threads, or if that's a euphamism for fork, or a simply a colloqualism meaning a new client.

    There is also mention of "Clone()" in the comments, which could be significant--or not.

    The only thing that stands out as being worthy of closer scrutiny is:open(DEBUG,">$DEBUG_LOG");

    Re-opening the same glob filehandle, never checking for success, and never closing it, in a concurrent environment, might or might not be a problem.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: memory leak Issue
by CountZero (Bishop) on Dec 09, 2008 at 06:08 UTC
    It has nothing to do with the memory-leak issue, but why are you using subroutine prototypes? They are not --as many erroneously think-- a way to check the validity of the argument list (see: When to use Prototypes? and Re: Are prototypes evil?).

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: memory leak Issue
by kyle (Abbot) on Dec 09, 2008 at 02:20 UTC

    In your new(), it seems you might have a reference to a "parent" object. If that parent also has a reference to the new object, that's a circular reference, and it will cause a memory leak. You'll need to use weaken from Scalar::Util in one of those places. There's a longer discussion of this in Re: deleteing references