Ryan
Ryan

Reputation: 451

Perl Threads - Capture Exit

I have code that spawns two threads. The first is a system command which launches an application. The second monitors the program. I'm new to perl threads so I have a few questions...

my $thr1 = threads->new(system($cmd));
sleep(FIVEMINUTES);
my $thr2 = threads->new(\&check);

my $rth1 = $thr1->join();
my $rth2 = $thr2->join();

1) Do I need a second thread to monitor the program? You can think of my sub routine call to &check as a infinite while loop which checks a text file for stuff the application produces. Could I just do this:

my $thr1 = threads->new(system($cmd));
sleep(FIVEMINUTES);
✓

2) I'm trying to figure out what my parent is doing after I run this code. So after I launch line 1 it will spawn that new thread, sleep, then spawn that second thread and then sit at that first join and wait. It will not execute the rest of my code until it joins at that first join. Is this correct or am I wrong? If I am wrong, then how does it work?

3) My first thread the one that launches the application can be killed unexpectedly. when this happens, I have nothing to catch that and kill the threads. It just says: "Thread 1 terminated abnormally: Undefined subroutine &main::65280 called at myScript.pl line 109." and then hangs there.

What could I do to get it to end the other threads? I need it to send an email before the program ends as well which I can do by just calling &email (another subroutine I made).

Thanks

Upvotes: 2

Views: 1257

Answers (3)

Yordan Georgiev
Yordan Georgiev

Reputation: 5440

In 2004-2006 I had the same challenges for 24/7 running perl app on Winblows... The only approach working was to use xml state files on disk to communicate the status of each component of the system... and make sure if threads are used every stat file handling occurred within a closure code block {} (big gotcha) The app ran at least 3 years on 100 machines 24/7 without errors ... If you are on a Unix-like OS I would suggest to use forks and interprocess communication. Use cpan modules, do not reinvent the wheel..

Upvotes: 1

ikegami
ikegami

Reputation: 386541

First of all,

my $thr1 = threads->new(system($cmd));

should be

my $thr1 = threads->new(sub { system($cmd) });

or simply

my $thr1 = async { system($cmd) };

You don't need to start a third thread. As you suspected, the main thread and the one executing system are sufficient.


What if the command finishes executing in less than five minutes? The following replaces sleep with a signal.

use threads;
use threads::shared;

my $done :shared = 0;

my $thr1 = async {
   system($cmd);

   lock($done);
   $done = 1;
   cond_signal($done);
};

{ # Wait up to $timeout for the thread to end.
   lock($done);
   my $timeout = time() + 5*60;
   1 while !$done && cond_timedwait($done, $timeout);
   if (!$done) {
      ... there was a timeout ...
   }
}

$thr1->join();

Upvotes: 4

dakillakan
dakillakan

Reputation: 260

Multithreading in Perl is a little hard to deal with, I would suggest using the fork() commands instead. I will attempt to answer your questions to the best of my ability.

1) It seems to me like two threads/processes are the way to go here, as you need to check asynchronously check your data.

2) Your parent works exactly as you describe.

3) The reason for your thread hanging could be that you never terminate your second thread. You said it was an infinite loop, is there any exit condition?

Upvotes: 0

Related Questions