Perl Multithreading - worker threads stops working -


i have following perl code makes asynchronous calls 2 external bioinformatics programs. first, runs blastjob, , takes results , runs exoneratejob. i've adapted code previous question moving code multi-threaded approach.

the problem frustrating because happens after several hours of running. leave program run overnight , find in morning exoneratejobs no longer running, new blastjobs still cranking through. there no reported errors or anything. tidbit of information i've gone , tested input queries logs show exoneratejobs stopped working. program completes fine if run small number of queries through it, if they're queries seemed have caused problems previously. since i'm not familiar rules of multithreading, i'd know if there's problem approach, or if it's potentially problem external programs called. here's bit of code:

#asynchronous calls blast , exonerate {    $blast_request_queue = thread::queue->new();    $exonerate_request_queue = thread::queue->new();     @blast_threads;    (1..num_blast_workers) {       push @blast_threads, async {          while (my $q = $blast_request_queue->dequeue()) {             @results = blastjob($q, $blastopts_ref);             foreach (@results) {                @args = ($q, $_);                $exonerate_request_queue->enqueue(\@args);             }          }           $exonerate_request_queue->end(); # i've tried , without line, result seems same       };    }     @exonerate_threads;    (1..num_exonerate_workers) {       push @exonerate_threads, async {          while (my $args_ref = $exonerate_request_queue->dequeue()) {             ($queryfile, $targetname) = @$args_ref; #de-reference args             $regex = qr/\q$targetname\e/;             #check target file             ($file_match) = grep { $_ =~ $regex } keys %targets;             if ($file_match) {                 $targetfile = $options{'t'} . $file_match;                 $result = exoneratejob($queryfile, $targetfile, $exonopts_ref);                 #print result file after job finished                 ($qname, $qpath, $qsuffix) = fileparse($queryfile);                 $outfn = $qname . ".exonerate_out";                 open(outfh, ">>$outfn") or print stderr "can't open $outfn: $!";                 print outfh $result;             } else {                 print stderr "target file not found: $targetname. can't run exonerate";             }          }       };    }      foreach (@queries) {         #concatenate query path name         $queryfile = $options{'q'} . $_;         $blast_request_queue->enqueue($queryfile);     }     #my $queryfile = $options{'q'} . $queries[3];     #$blast_request_queue->enqueue($queryfile);     $blast_request_queue->end();        $_->join() @blast_threads;    $exonerate_request_queue->end();    $_->join() @exonerate_threads; }  #i'm using ipc::run launch programs. #there error handling believe should catch probs sub blastjob {     ($query, $blastopts_ref) = @_;     #de-reference blast options     @blastcmd = @$blastopts_ref;     ($blastout, $err); #for blast output     #add query information after first blast option     splice(@blastcmd, 1, 0, ("-query", $query));     ($qname, $qpath, $qsuffix) = fileparse($query);     print "running $blastcmd[0]: query $qname...\n";     run \@blastcmd, \undef, \$blastout, \$err;     if ($err) {         print "error in blast query $qname. $err\n";     }     @results = split("\n", $blastout);     return uniq(@results); }  sub exoneratejob {     ($query, $target, $exonopts_ref) = @_;     #de-reference exonerate options     @exoncmd = @$exonopts_ref;     ($exonout, $err); #for exonerate output     #add program, query, , target information exonerate options     unshift (@exoncmd, ("exonerate", "-q", $query, "-t", $target));     ($qname, $qpath, $qsuffix) = fileparse($query);     ($tname, $tpath, $tsuffix) = fileparse($target);     eval {         print "running exonerate: query $qname, target $tname...\n";         run \@exoncmd, \undef, \$exonout, \$err, timeout(240);         if ($err) {             print stderr "error in exonerate query $qname, target $tname. $err\n";         }     };     if ($@ =~ /timeout/) {         print stderr "error: timeout in exonerate query $qname, target $tname\n";     }      return $exonout; } 

without source information, can't test - money on first time you:

$exonerate_request_queue->end(); 

in async block.

because think it's quite possible there, as soon close

$blast_request_queue->end();  

then thread exit after, close 'output' queue, , in doing - mean lose pending, because queue closed.


Comments