Perl multithreading and foreach

I am writing a simple Perl script that should run other Perl scripts at the same time. I do not know how to make the main program wait for threads to execute. Sleep is NOT a suitable solution for many reasons. This is my "main" script:

#!/usr/bin/perl use threads; main: { if ($#ARGV == -1) { usage(); exit(1); } my $hostname = $ARGV[0]; my $thrssh = threads ->create(\&ssh, $hostname); my $thrdns = threads ->create(\&dns, $hostname); my $thrping = threads ->create(\&ping, $hostname); my $thrsmtp = threads ->create(\&smtp, $hostname); my $thrproxy = threads ->create(\&proxy, $hostname); } sub ssh { threads->detach(); my $hostname = @_; #print "SSH\n"; #LAUNCH SSH SCRIPT } #OTHER SUBROUTINES... sub proxy { threads->detach(); my $hostname = @_; #print "PROXY\n"; #LAUNCH PROXY SCRIPT } 

If I try to run this script, the first thing I can notice is that the prints are "sequential", I thought the text was spoiled, but maybe Print is exclusive, which I don't know. The main problem is that the last two routines do not have time to execute.

 SSH DNS PING Perl exited with active threads: 2 running and unjoined 0 finished and unjoined 0 running and detached 

If I use union instead of detaching, the routines become "sequential", for example, if I put sleep in sub ssh, other threads will wait before starting. I want them to be parallel, and the main program will close ONLY when all threads are completed, any help?

I really have another question, if I need to run multiple threads in a foreach cicle, when should I join them? i.e:

 my $thrssh; foreach $mynode ($nodeset->get_nodelist) { #... $thrssh = threads ->create(\&ssh, $port, $hostname); #... } $thssh->join(); 

Is it correct?

+4
source share
1 answer

You need to join remove all your threads from the main thread after all of them have been started. Do not detatch unless you want the interpreter to shut down while the threads are not already running.

 ... my $thrssh = threads ->create(\&ssh, $hostname); my $thrdns = threads ->create(\&dns, $hostname); ... $thrssh->join(); $thrdns->join(); ... 

Regarding your editing: no, this is wrong. You need to save a link to each stream created, otherwise you will not be able to join them.

Do something like:

 my @thrs; foreach $mynode ($nodeset->get_nodelist) { #... $thrssh = threads ->create(\&ssh, $port, $hostname); push @thrs, $thrssh; #... } $_->join() for @thrs; 
+9
source

Source: https://habr.com/ru/post/1381086/


All Articles