2017-07-21 1 views
0

Je cours un Monte Carlo sur plusieurs processeurs, mais il raccroche beaucoup. J'ai donc mis en place ce code perl pour tuer l'itération qui raccroche le monte carlo et passer à l'itération suivante. Mais j'ai quelques erreurs, je n'ai pas encore compris. Je pense qu'il dort trop longtemps et il supprimera le fichier out.mt0 avant qu'il ne le cherche. Voici le code:Expiration d'un processus fourchu

 my $pid = fork(); 
    die "Could not fork\n" if not defined $pid; 

    if ($pid==0){ 

     print "In child\n"; 

     system("hspice -i mont_read.sp -o out -mt 4");wait; 
     sleep(.8);wait; 
     exit(0); 

    } 

     print "In parent \n"; 




$i = 0; 

    $mont_number = $j - 1; 

    out: while (1){ 

    $res=waitpid($pid, WNOHANG); 

    if ($res == -1) { 

     print "Successful Exit Process Detected\n"; 
     system("mv out.mt0 mont_read.mt0");wait; 
     sleep(1);wait; 
     system("perl monte_stat.pl > rel_out.txt"); wait ; 
     system("cat stat_result.txt rel_out.txt > stat_result.tmp"); wait; 
     system("mv stat_result.tmp stat_result.txt");wait; 
     print "\nSim #$mont_number complete\n";wait; 
     last out; 

    } 

    if($res != -1){ 

    if($i>=$timeout){ 

     $hang_count = $hang_count+1; 
     system("killall hspice");wait; 
     sleep(1); 
     print("time_out complete\n");wait; 
     print "\nSim #$mont_number complete\n";wait; 
     last out; 

    } 

    if($i<$timeout){ 

     sleep $slept;wait; 

    } 

    $i=$i+1; 

    } 

    } 

Ceci est l'erreur:

Illegal division by zero at monte_stat.pl line 73, <INHSPOUT> line 2. 
mv: cannot stat `out.mt0': No such file or directory 
Illegal division by zero at monte_stat.pl line 73, <INHSPOUT> line 1. 
mv: cannot stat `out.mt0': No such file or directory 
Illegal division by zero at monte_stat.pl line 73, <INHSPOUT> line 1. 
mv: cannot stat `out.mt0': No such file or directory 
Illegal division by zero at monte_stat.pl line 73. 
mv: cannot stat `out.mt0': No such file or directory 
Illegal division by zero at monte_stat.pl line 73. 
mv: cannot stat `out.mt0': No such file or directory 
mv: cannot stat `out.mt0': No such file or directory 
mv: cannot stat `out.mt0': No such file or directory 
Illegal division by zero at monte_stat.pl line 73, <INHSPOUT> line 3. 
mv: cannot stat `out.mt0': No such file or directory 
Illegal division by zero at monte_stat.pl line 73, <INHSPOUT> line 1. 
mv: cannot stat `out.mt0': No such file or directory 

Quelqu'un pourrait-il me donner une idée où chercher le déboguer. merci

+2

Afficher un exemple minimal, complet et vérifiable. Ne faites pas que lier votre code. –

+0

Je ne vois aucun fil dans le code que vous avez posté. – duskwuff

+0

@duskwuff J'ai ajouté la partie thread. Ceci est le code complet: https://github.com/aliyah3/Multi-thread-with-Perl/blob/master/Times_hspice.perl –

Répondre

3

Selon les erreurs, il semble que votre hslice plante. Mais il y a d'autres problèmes.

Voici d'abord un exemple de travail le plus proche possible de votre code.

use warnings; 
use strict; 
use feature 'say'; 
use POSIX qw(:sys_wait_h); 
$| = 1; 

my ($timeout, $duration, $sleep_time) = (5, 10, 1); 

my $pid = fork // die "Can't fork: $!"; 

if ($pid == 0) 
{ 
    exec "echo JOB STARTS; sleep $duration; echo JOB DONE"; 
    die "exec shouldn't return: $!"; 
}  
say "Started $pid"; 
sleep 1; 

my $tot_sec;  
while (1) 
{ 
    my $ret = waitpid $pid, WNOHANG; 

    if ($ret > 0) { say "Child $ret exited with: $?"; last; } 
    elsif ($ret < 0) { say "\nNo such process ($ret)"; last; } 
    else    { print " . " } 

    sleep $sleep_time; 

    if (($tot_sec += $sleep_time) > $timeout) { 
     say "\nTimeout. Send 15 (SIGTERM) signal to the process."; 
     kill 15, $pid; 
     last; 
    } 
} 

Avec $duration (du travail) mis à 3, plus courte que $timeout, nous obtenons

 
Started 16848 
JOB STARTS 
. . . JOB DONE 
Child (JOB) 16848 exited with: 0 

alors qu'avec $duration ensemble à 10 nous obtenons

 
Started 16550 
JOB STARTS 
. . . . . 
Timeout. Send 15 (SIGTERM) signal to the process. 

et le travail est tué (attendez 5 secondes de plus – le JOB DONE shouldn n'apparaisse pas).

Commentaires sur le code dans la question

  • Si vous fork seulement d'exécuter un travail il n'y a aucune raison pour system. Juste exec ce programme

  • Pas besoin de wait après system, et c'est faux. Le system comprend une attente

  • Le wait n'appartient pas après print et sleep, et il est faux

  • Pas besoin de débourser pour killall afin de tuer un processus

  • Si vous vous En utilisant system le programme s'exécutera dans un nouveau processus avec un autre PID. Alors plus est nécessaire pour trouver ce PID et le tuer. Voir Proc::ProcessTable et this post, par exemple

  • Le code ci-dessus a besoin de contrôles si le processus a effectivement été tué

remplacer votre ligne de commande au lieu de echo ... et ajouter des contrôles pour au besoin.

Une autre option consiste simplement à dormir pendant une période de $timeout puis de vérifier si le travail est terminé (enfant sorti).Cependant, avec votre approche, vous pouvez faire d'autres choses tout en interrogeant. Une autre option est d'utiliser alarm.