views:

149

answers:

3

I have a script which needs to periodically start programs out of a array with program names via Perl on Linux. The problem is that from time to time one of the programs takes too long/hangs and needs to be aborted.

Currently I am starting the program using qx/$cmd/ in a seperate thread which reads from a shared start queue. The main thread enqueues every x seconds a new element into the queue. If there are elements in the queue, the main thread kills the child thread and starts a new child.

This works fine from a functional perspective, but now I have realised that this leads to a memory leak. How would you design such a program ? Is there any CPAN module which can help? Please let me know if you need further code to understand the problem.

The main thread looks like this:

     if (!$startQueue->pending) {
   $startQueue->enqueue($programList[$i++]);
 } else {
   $log->warn("Aborting hanging execution");
   $starterThread->kill('KILL')->detach();
   $log->info("Creating new thread");
   $starterThread=threads->create("starterThread");
 }

The child thread like this:

sub starterThread{
  $SIG{'KILL'}=sub{threads->exit();};
  $log->info("Starter Thread started");
  while() {
    my $programName=$startQueue->dequeue();
    $log->debug("programName:$programName");
    qx/$programName/;
  }
}
A: 

An alternative to a manager process like that is a PID file with a timestamp (i.e. contents are pid timestamp), like sendmail uses. Then you start up a new copy of the process every minute from cron, or something, and if an old process is there, the new process either dies (if the timestamp is recent) or kills the old process (if the timestamp is old).

I don't actually know why your manager process should necessarily lead to a memory leak, though. Have you firmly established that this is the case? What's your reasoning?

chaos
I think that the thread kill does not work properly - killing threads is a dirty operation in any case, but perl never seems to release the memory. I will try to minimise the issue for a bug report.
weismat
+2  A: 

You could have a look at Parallel::ForkManager which lets you manage a fixed number of child processes at any given time. Does the program name array remain static through the life of the script or does it update itself continuously?

The memory leak sounds fishy; have you profiled your script and determined absolutely that the kill/enqueue leads to the memory leak?

muteW
I am using Log4Perl and I can see with every thread kill an increase in the size of the process via ps and a reduction in free memory in the system via free -m.
weismat
I have added the relevant code parts to the start of the discussion.
weismat
Can I use Parallel::ForkManager inside a multi-threaded application? The program will be two threads in any case anyway....
weismat
From the looks of the code it makes no sense to use Parallel::ForkManager, could you possibly provide a larger listing? I am having trouble understanding the $startQueue bits.
muteW
A: 

Normally use ALARM signal + self slaying within the program itself rather than a chaser program.

hpavc