Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2913 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  Gestion d'un processus avec timeout

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Gestion d'un processus avec timeout

n°1739328
Predicator
Posté le 30-05-2008 à 11:43:15  profilanswer
 

Bonjour,

 

J'ai un problème en Perl que je n'arrive pas à résoudre.

 

J'ai besoin de lancer une commande (en fait mon script perl gère un lot et lance la commande en séquence sur chaque élément du lot), et de l'arrêter si elle prend trop de temps.

 

J'ai creusé plusieurs méthodes, donc la plus "propre" semble être l'utilisation de alarm et die, mais ça ne marche pas dans mon cas.

 

Voici le code de "test" de la méthode, modifiée pour mon usage, à partir du code qu'on peut trouver un peu partout sur le net :

 
Code :
  1. #!/usr/bin/perl -w
  2. $gcom = "<ma commande>";
  3. $time = 5;
  4. sub execCom {
  5. $com = $_[0];
  6. eval {
  7.  local $SIG{ALRM} = sub { die "$com est parti en boucle\n" };
  8.  alarm $time;
  9.  system($com);
  10.  alarm 0;
  11. };
  12. if ($@) {
  13.  die "#3xyz# : $@\n";
  14.  # délai dépassé : time out
  15. } else {
  16.  # délai non dépassé
  17.  print "#8xyz# : Délai non dépassé\n";
  18. }
  19. }
  20. system ("touch 1.t" );
  21. &execCom("$gcom" );
  22. system ("touch 2.t" );
  23. &execCom("$gcom" );
  24. system ("touch 3.t" );
  25. &execCom("$gcom" );
  26. system ("touch 4.t" );
  27. &execCom("$gcom" );
  28. system ("touch fin.t" );
  29. system ("ll -rt *.t" );
 

Au final, seule la première commande est exécutée (les lignes 28 et 29). Elle dépasse le timeout, mais n'est pas arrêtée... Les lignes suivantes (30 et +) ne sont jamais exécutées.

 

Quelqu'un pourrait m'expliquer ?

 

J'ai aussi regardé du côté de "ulimit" en bash/sh et "limit cputime" en csh/tcsh, mais je me trouve face à un comportement étrange, et surtout, des impossibilité de changer les valeurs... De plus comme c'est dépendant du shell, j'ai moins confiance.

 

Merci de m'aider :)


Message édité par Predicator le 30-05-2008 à 11:45:10
mood
Publicité
Posté le 30-05-2008 à 11:43:15  profilanswer
 

n°1739386
Predicator
Posté le 30-05-2008 à 14:16:11  profilanswer
 

Bon, à défaut de réponse et vu que c'est assez pressé, j'ai utilisé une autre méthode. Pas propre il est vrai, mais fonctionnelle (je n'ai pas trouvé de faille, même je ne doute pas qu'il y en ait une).
 
Donc l'idée est qu'un script A gère le lot, et appelle un script perl B, via la commande system.
 
Voici le contenu du script B (avec commentaire de debuggage non retirés) :
 

Code :
  1. #!/usr/bin/perl -w
  2. $gcom = $ARGV[0];
  3. $time = $ARGV[1];
  4. $pid = fork();
  5. if (not defined $pid) {
  6. print "Plus de ressources...\n";
  7. exit(1);
  8. }
  9. if ($pid == 0) {
  10. # fils, on lance le programme
  11. exec($gcom);
  12. } else {
  13. #print "$pid\n";
  14. $cpt = 0;
  15. while($cpt < $time) {
  16.  # On teste l'existence du pid
  17.  open COM, ("ps -p $pid|grep $pid|" );
  18.  @lines = <COM>;
  19.  close COM;
  20.  print "@lines\n";
  21.  if ($lines[0] =~ m/$pid/) {
  22.   print "$pid is running\n";
  23.   if ($lines[0] =~ m/defunct/) {
  24.    print "Attente du fils que le père meurt\n";
  25.    exit(0);
  26.   } else {
  27.    print "$cpt : Attente d'une seconde\n";
  28.    sleep(1);
  29.   }
  30.  } else {
  31.   exit(0);
  32.  }
  33.  $cpt++;
  34. }
  35. open COM, ("ps -p $pid|grep $pid|" );
  36. @lines = <COM>;
  37. close COM;
  38. if ($lines[0] =~ m/$pid/) {
  39.  print "Sortie de boucle, $pid is running\n";
  40.  print "$pid must be killed... Cya in Hell my friend !\n";
  41.  kill 9, $pid;
  42. }
  43. }


 
Je vais utiliser ce script dès cet après-midi, mais je reste ouvert à toute évolution, donc ne vous privez pas :)

n°1739424
Taz
bisounours-codeur
Posté le 30-05-2008 à 15:41:30  profilanswer
 

L'autre jour j'ai eu le même problème, je sais pas pourquoi, je m'en sortais pas avec l'alarm, ça bloquait souvent pour une raison que je n'ai pas réussi à déterminer. donc au final j'ai fait une méthode ou je lance un autre processus pour tuer l'autre.
 

Code :
  1. sub _find_started_process
  2. {
  3.     my $spawner = shift;
  4.     my $child = `ps -elf | awk '\$5 == $spawner { print \$4 }`;
  5.     chomp $child;
  6.     print STDERR "Real subprocess is $child\n" if ($child);
  7.     return $child;
  8. }
  9. sub _start_killer
  10. {
  11.     my ($pid, $gracetime) = @_;
  12.     my $killer = fork;
  13.     return $killer if $killer;
  14.     POSIX::setsid;
  15.     chdir '/';
  16.     #fork && exit;
  17.     print STDERR "Killer $$ started for PID $pid with gracetime $gracetime\n";
  18.     sleep $gracetime;
  19.     if (kill(0, $pid)) {
  20.         do {
  21.             print STDERR "Killing $pid\n";
  22.         } while (kill(9, $pid) != 1);
  23.     }
  24.     exit;
  25. }
  26. sub _run
  27. {
  28.     my $cmd = shift;
  29.     my $data = undef;
  30.     my $pid = undef;
  31.     my $killerpid = undef;
  32.     eval {
  33.         my $timeout = 20;
  34.         ($pid = open(INPUT, '-|', $cmd)) or die("cannot start : $!" );
  35.         print STDERR "Running $cmd with PID $pid\n";
  36.         my $started = _find_started_process($pid);
  37.         if ($started) {
  38.             $killerpid = _start_killer($started, $timeout);
  39.         }
  40.         $data = do { local($/); <INPUT> };
  41.         close(INPUT);
  42.     };
  43.     my $error = @_;
  44.     if ($killerpid && kill(0, $killerpid)) {
  45.         do {
  46.             print STDERR "Killing killer $killerpid\n";
  47.         } while (kill(9, $killerpid) != 1);
  48.         waitpid($killerpid, 0);
  49.     }
  50.     # _start_killer($killerpid, 0);
  51.     if ($error) {
  52.         die "Couldn't not run '$cmd' : $error";
  53.     }
  54.     return $data;
  55. }


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  Gestion d'un processus avec timeout

 

Sujets relatifs
[DB2] gestion de transactiongestion de dépots en sql
Gestion des événementsAide pour faire MCD - Gestion de stocks
Gestion d'un championnat avec les graphes.Tomcat: régler le timeout
[Résolu] gestion mémoire en javaGestion des groupes Active Directory (débutant)
[SPIP] gestion accès restreint par groupeProcessus PHP?
Plus de sujets relatifs à : Gestion d'un processus avec timeout


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR