http://qs321.pair.com?node_id=509586

JFarr has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks, I have a thread question that I have not been able to solve. I receive this error message: A thread exited while 7 threads were running, <FILE> line 15. I'm using "use threads" and "use threads::shared". basically I have this setup:
foreach $host (@syshost) { $threadHost = threads->new(\&runSeries, $host); } sub runSeries { my $stuff = @_; < parse through $stuff...and do data manipulation> $threadStuff = threads->new(\&PrintOut, $stuff)->join; }
PrintOut just prints data to the screen. I know that if I use a join in the first thread call, my problem goes away, except that this drastically slows the program down. Is there a way to stop the first thread from exiting until all the other threads are finsished? Thanks

Replies are listed 'Best First'.
Re: Thread exit errors
by dave_the_m (Monsignor) on Nov 17, 2005 at 21:55 UTC
    Is there a way to stop the first thread from exiting until all the other threads are finsished?
    In the main thread, do something like:
    $_->join for threads->list;
    although that could interfere with the threads being created in runSeries (I don't understand why you create a new thread there), in which case do this instead:
    my @threads; foreach $host (@syshost) { push @threads, threads->new(\&runSeries, $host); } $_->join for @threads;

    Dave.

      Thanks Dave. I'm still very noobish to Perl, so I have a question on your response. the $_->join for threads->list, what does this do. The problem we are having, is that are services have a delay in their response time, being that our farthest host is between 200-400 miles from our distribution. Is this command going to keep the threads alive until a response if found? The reason for the multi threads is that the main thread, launches a method that is launching other threads to search for all of the servies on each host. So,
      foreach $host(@syshosts) { @sysThread = threads->new( \&findHostNodes, $host ); } sub findHostNodes { my $host = @_; #print some stuff about the node #now find the services on the host foreach $service (@r21services) { @serviceThread = threads->new(\@shutdonwServices, $service); } } sub shutdownServices { shut down the windows services we are looking for }
      From you response, in your opinion, what is the better method? Thanks, Jeff
        $_->join for threads->list, what does this do.

        It simply waits for, and then joins, any remaining threads.

        Your problem is simply to ensure that the main process doesn't exit until all threads have been joined. My example is just a simple way to ensure that all remaining threads have been joined.

        Please bear in mind that threads in perl are extremely expensive to create and consume a lot of memory, so I suspect that creating new threads in findHostNodes is a bad idea.

        Dave.

Re: Thread exit errors
by zentara (Archbishop) on Nov 18, 2005 at 13:35 UTC
    This example might show you a way. One thing you might be missing is that the thread must reach the end of it's code block, or return, before it can be joined. So I usually use a shared var 'die' to signal a thread to return immediately. That way, if you want to exit without all those warnings, you set the 'die' = 1 for each thread, then join them after they have returned.

    In the following example, I join them as they finish, but you can easily hold them in an unjoined condition, until all threads are done. I don't know why you would want that, but it would be easy to do.

    #!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; $| = 1; my %threads; foreach (1..10){ share $threads{$_}{'die'}; share $threads{$_}{'data'}; $threads{$_}{'die'} = 0; $threads{$_}{'data'} = 0; } foreach (1..10) { $threads{$_}{'thread'} = threads->new('StartTest'); } my @threads = (1..10); while(1){ foreach my $t (@threads){ if($threads{$t}{'data'} > 5){ $threads{$t}{'die'} = 1; $threads{$t}{'thread'}->join; @threads = grep { $_ != $t } @threads; } } if(scalar @threads == 0){last} } print "\n", "All threads done\n"; ########################################################## sub StartTest { my $self = threads->self; print "Thread ", $self->tid, " started\n"; while(1){ if( $threads{$_}{'die'} == 1){return} else{ print "From thread $self->",$threads{$_}{'data'}++,"\n"; sleep 1; }; } print "Thread ", $self->tid, " ending\n"; }

    I'm not really a human, but I play one on earth. flash japh