Friday, March 14, 2008

Where Wizards Fear To T"h"read

Since PERL is a tool of choice for many of us Tivolians when it comes to automations and integrating systems with Tivoli products, I thought it could be of help to others to throw out a few gotchas I've encountered programming Perl threads. Please note that I'm not referring to "forking".

Though Perl threads can help speed up things in a Tivoli automation or integration script, they can also add headaches and frustration to ones life. The following three pointers should help reduce some of the strive...

1. Using nested data structures with PERL THREADS.

When using threads it is usual to share data. Sharing complex data structures works very well for a single threaded (single process) PERL script. But once the main process starts producing child threads, then hell breaks loose with the complex data structure as PERL can as of the writing of this document, deal with ONLY one level deep references to a SHARED data structure like an array or hash.
If you encounter and error like:

Invalid value for shared scalar at ...

then you've nested too much. Keep your reference to shared arrays and hashes to one-level down and you'll be ok.


2. Creating an ALARM signal handler within a child thread.
Often in Tivoli a person will call "w" command/s within a PERL program to perform some operation on a Tivoli resource. But it often happens that a "w" command hangs or takes too long to complete. What many often do is create an ALARM to timeout the command so the process continues execution when some specified time has elapsed. This usually works OK in a single thread program, but things start going out of hand when there's more than one thread executing in a PERL program. What happens with threads is that instead of timing-out the particular intended call within a CHILD thread, the whole PERL program quits executing! That is the main thread and its children threads die!!! The one work-around I've always found effective is to include code that looks as follows in the MAIN program flow. Make sure this code appears in the main thread and NOT in a child-thread.


$SIG{ALRM} = sub {}; #Just here to workaround the threads "Alarm clock" bug


That amazingly does the trick!


3. Handling the CTRL C interrupt within a threaded Perl program.
To avoid resource contention, often a person would prevent more than one instance of a PERL program from running by creating a lock-file at the begin of the program and then removing the file just before end of the program. But a problem comes when for some known or unknown reason, the PERL program receives an INT signal and terminates after creating the lock-file, but before executing to a point where the lock-file gets removed. Thus preventing any subsequent run of the program. It's easy to circumvent this situation and handle the signal in a single thread PERL program, but it can be a pain doing like-wise in a multi-threaded PERL program where a simple $SIG{INT} may do anything but catch the interrupt. For instance the norm would be to do something like:

$SIG{INT} = sub { "code that removes the lock-file"; die};

Trying to handle the interrupt this way in a multi-threaded PERL program may actually result with the program dumping core. Including the following chunk of code/subroutine most often does magic and beautifully handles the interrupt signal without fail:



use sigtrap qw[handler sig_handler INT TERM QUIT PIPE];
use Swith;

sub sig_handler {
my($sig) = shift;
print "Caught signal $sig";

switch($sig) {
case ["INT","TERM","QUIT"] {
unlink "/tmp/dashlock";
print "Exiting";
exit(0);
}
case "PIPE" {
print "Continuing";
}
}
}



I'm sure the above is not all there is on PERL threading gotchas, I however hope the pointers save you time and heart-ache should you have to deal with Perl threading in the near future and encounter similar issues.

That's all folks!

Adios,
J. Napo Mokoetle
"Even the wisest man is yet to learn something."

3 comments:

Guy said...

Hi,

Do you have a working example for solving ALARM - timout issues in threads ?

10x

Guy

Frank Tate said...

Hey Guy,

Sorry, I don't have one handy.

-- Frank

Ranjeet Mishra said...

this provides a useful insight..thanks