Multithreading for perl code
I need to know how to implement multi threading for the following code . I need to call this script every second but the sleep timer processes it after 2 seconds . In total script call itself after every 3 seconds. But i need to call it every second , can anybody provide me a solution to it or point me to right direction.
#!usr/bin/perl use warnings; sub print < local $gg = time; print "$gg\n"; >$oldtime = (time + 1); while(1) < if(time >$oldtime) < &print(); sleep 2; $oldtime = (time + 1); >>
1 Answer 1
Here is a simple example of using threads:
use strict; use warnings; use threads; sub threaded_task < threads->create(sub < my $thr_id = threads->self->tid; print "Starting thread $thr_id\n"; sleep 2; print "Ending thread $thr_id\n"; threads->detach(); #End thread. >); > while (1)
This will create a thread every second. The thread itself lasts two seconds.
To learn more about threads, please see the documentation. An important consideration is that variables are not shared between threads. Duplicate copies of all your variables are made when you start a new thread.
If you need shared variables, look into threads::shared .
However, please note that the correct design depends on what you are actually trying to do. Which isn’t clear from your question.
Some other comments on your code:
- Always use strict; to help you use best practices in your code.
- The correct way to declare a lexical variable is my $gg; rather than local $gg; . local doesn’t actually create a lexical variable; it gives a localized value to a global variable. It is not something you will need to use very often.
- Avoid giving subroutines the same name as system functions (e.g. print ). This is confusing.
- It is not recommended to use & before calling subroutines (in your case it was necessary because of conflict with a system function name, but as I said, that should be avoided).
Problem with multi-threaded Perl script run via SSH on Linux
I cannot understand the behavior of the following simple Perl script in case I run it remotely via SSH.
use strict; use warnings; use threads; use threads::shared; use POSIX; my $print_mutex : shared; ################################################################################ sub _print($) < my $str = shift; lock($print_mutex); my $id = threads->tid(); my $time = strftime('%H:%M:%S', localtime time); print "$time [$id] $str"; return; > ################################################################################ sub run() < for my $i (1 .. 3) < _print("Begin $i\n"); sleep 1; _print("End $i\n"); >return threads->tid(); > ################################################################################ _print "Starting test.\n"; my @threads; for my $thr_num (1 .. 2) < my $thr = threads->create('run'); push @threads, $thr; _print "Thread created.\n"; > foreach (@threads) < my $id = $_->join; _print "Thread '$id' finished.\n"; > _print "Test finished.\n"; ################################################################################
$ perl /tmp/a.pl 14:25:54 [0] Starting test. 14:25:54 [0] Thread created. 14:25:54 [1] Begin 1 14:25:54 [0] Thread created. 14:25:54 [2] Begin 1 14:25:55 [1] End 1 14:25:55 [1] Begin 2 14:25:55 [2] End 1 14:25:55 [2] Begin 2 14:25:56 [1] End 2 14:25:56 [1] Begin 3 14:25:56 [2] End 2 14:25:56 [2] Begin 3 14:25:57 [1] End 3 14:25:57 [0] Thread '1' finished. 14:25:57 [2] End 3 14:25:57 [0] Thread '2' finished. 14:25:57 [0] Test finished. $
However, when I run it via SSH (on the same local host, but it doesn’t matter) I get very strange results (look closely at timestamps and thread IDs):
$ ssh localhost 'perl /tmp/a.pl' 14:26:11 [0] Starting test. 14:26:11 [0] Thread created. 14:26:11 [1] Begin 1 14:26:12 [1] End 1 14:26:12 [1] Begin 2 14:26:13 [1] End 2 14:26:13 [1] Begin 3 14:26:14 [1] End 3 14:26:11 [2] Begin 1 14:26:12 [2] End 1 14:26:12 [2] Begin 2 14:26:13 [2] End 2 14:26:13 [2] Begin 3 14:26:14 [2] End 3 14:26:11 [0] Thread created. 14:26:14 [0] Thread '1' finished. 14:26:14 [0] Thread '2' finished. 14:26:14 [0] Test finished. $
I’ve never seen this in single-threaded Perl scripts and I noticed that I started seeing the problem with I/O right after the first thread has been created. I was able to reproduce the problem with the latest Perl-5.12 on Windows, so I don’t think the problem is Perl/OS specific. Could someone please explain what’s wrong here?
Shell Programming and Scripting
17, 0
I need to write a perl script to execute external programs and grab the output and return code. Each program should be killed if it has not completed within X seconds.
Imagine that the script goes something like this :
foreach $cmd (@commands) $pid = execute($cmd, $timeout);
push (@pids, $pid);
>
# pid included above in case it’s needed
foreach (@commands) if ($output) print «Output of $cmd was $output, it comleted in $duration seconds\n»;
> else print «$cmd did not complete in the allowed time and was killed»;
>
. what could the execute function look like ?
Currently I have something roughly like this
sub execute my $cmd = shift;
my $pid;
unless ($pid = fork) exec(«$cmd > /tmp/out.$$»);
>
return $pid; # returning this pid, just in case 🙂
>
This works, but I don’t feel it’s very elegant. I have to keep track of all pids and kill processes that take more than X seconds using ‘ps’ to track processes and ‘kill’ to kill them. Ideally I’d like something platform independent. I’ve looked into multi threaded programming but I’m unfamiliar with this and I’m stomped.
Example of my attempted code to achieve the same as above:
sub execute my $cmd = shift;
system(«$cmd >/tmp/out.$$»);
>
foreach $cmd (@commands) my $thread[$i++] = threads->create(\&execute,$cmd);
>
If I run this code I get an error like
A thread exited while 5 threads were running.
. where do I go from here ? How do I wait until each thread has completed, and how would I kill slow threads ?
Should I be looking at a completely different approach ?
Any assistance appreciated !