Reputation: 53
I am relatively new to perl and I have written a program to process same operations on set of OS images. Since the operations were same , I used threads. A scaled down version of the program is attached. The problem is , the main program never comes out and wait for ever . On tracing, I see that the main program is waiting on "tee" command. Anything I have goofed up here ?
I am on CentOS 6.7 with Perl version 5.1 and I cant move forward because of many other dependencies :(
#!/usr/bin/perl -w
use threads;
my $tee_pid= open my $tee, "|-", "tee mylog";
my @images = ( "image1" , "image2");
foreach my $image (@images){
$_ = async { do_ops_on_image() };
sleep ( 60 );
}
while( threads->list ) {
for my $joinable ( threads->list( threads::joinable ) ) {
$joinable->join;
}
}
print "All thread completed \n";
close $tee;
sub do_ops_on_image
{
my $time = `date`;
my $id = threads->tid();
sleep (120) if ( $id ==2 );
print $tee "my $id started at $time \n";
}
Upvotes: 3
Views: 177
Reputation:
I am relatively new to perl […] I used threads.
This is your problem.
Perl threads are weird. They have a number of unexpected and undesirable behaviors; in particular, most variables cannot safely be shared between threads, and some modules do not support use in a threaded environment at all. To quote the threads
documentation:
The "interpreter-based threads" provided by Perl are not the fast, lightweight system for multitasking that one might expect or hope for. Threads are implemented in a way that make them easy to misuse. Few people know how to use them correctly or will be able to provide help.
The use of interpreter-based threads in perl is officially discouraged.
For many common applications, the Parallel::ForkManager
module may be a more appropriate choice.
Upvotes: 3
Reputation: 2403
This seems to be a bug in perl that was fixed in version 5.14.0. If you really can't install a newer perl (in addition to the system perl), then try to avoid the $tee shared filehandle, which is what is causing the main thread to hang.
Also, your code to wait for the child threads to finish uses an active CPU loop which will burn lots of CPU. If you just want to wait until all child threads are finished, do something like
my @threads;
...
for ... {
push @threads, async { ... }
}
...
$_->join for @threads;
Upvotes: 7