Fork et die

Fork et die - Perl - Programmation

Marsh Posté le 18-06-2009 à 10:55:40    

Bonjour,
 
J'ai un programme qui appelle des connexions SSH sur différents serveurs dans une boucle.
Pour simuler un timeout j'utilise des fork, et si le timeout arrive a expiration je tue le fils.
Si la connexion plante ou qu'il y a un problème, je demande également au fils de se tuer.  
 
Mon problème est que si je lui demande de se tuer a l'intérieur d'une fonction qui est dans le code mais a l'extérieur du "if $fork == 0" le programme se tue, si je place la fonction à l'intérieur par contre j'ai le comportement souhaité (mais j'aimerai bien mettre mes fonctions a l'extérieur dans un souci de lisibilité).
 
En bref, le comportement suivant est-il normal ?
 

Code :
  1. Exemple 1 : Le programme se tue
  2. for my $hosts (@hosts){
  3. my $pid = fork;
  4. if ($pid == 0) {
  5.  &kill-me();
  6. }
  7. }
  8. sub kill-me {
  9. die;
  10. }
  11. Exemple 2 : Le fils meurt
  12. for my $hosts (@hosts){
  13. my $pid = fork;
  14. if ($pid == 0) {
  15.  sub kill-me {
  16.   die;
  17.  }
  18.  &kill-me();
  19. }
  20. }


Reply

Marsh Posté le 18-06-2009 à 10:55:40   

Reply

Marsh Posté le 18-06-2009 à 17:52:05    

ben fork te donnes le pid tu fils créé.

Reply

Marsh Posté le 18-06-2009 à 17:59:49    

Pourquoi ne pas passer par kill?
J'ai pas testé, mais je ferais ainsi pour ton premier cas

Code :
  1. for my $hosts (@hosts) {
  2.    my $pid = fork;
  3.    if ($pid == 0) {
  4.        &kill-me($pid);
  5.    }
  6. }
  7. sub kill-me {
  8.    my $pid = shift;
  9.    kill 9, $pid;
  10. }


 
Je ne sais pas trop ce que signifie

Code :
  1. if ($pid == 0) {
  2.  sub kill-me {
  3.   die;
  4.  }


car habituellement, on ne définit pas un sub à l'intérieur d'une autre procédure.
Le fils meurt et pas le père? bizarre.
A+,

Message cité 2 fois
Message édité par gilou le 18-06-2009 à 18:08:04

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 18-06-2009 à 22:02:30    

gilou a écrit :

Pourquoi ne pas passer par kill?
J'ai pas testé, mais je ferais ainsi pour ton premier cas

Code :
  1. for my $hosts (@hosts) {
  2.    my $pid = fork;
  3.    if ($pid == 0) {
  4.        &kill-me($pid);
  5.    }
  6. }
  7. sub kill-me {
  8.    my $pid = shift;
  9.    kill 9, $pid;
  10. }


 
Je ne sais pas trop ce que signifie

Code :
  1. if ($pid == 0) {
  2.  sub kill-me {
  3.   die;
  4.  }


car habituellement, on ne définit pas un sub à l'intérieur d'une autre procédure.
Le fils meurt et pas le père? bizarre.
A+,


T'es obligé de kill. Sinon tu peux tenter des fourberies avec alarm + nettoyage des fils du fils ...

Reply

Marsh Posté le 19-06-2009 à 09:26:26    

gilou a écrit :

Pourquoi ne pas passer par kill?
J'ai pas testé, mais je ferais ainsi pour ton premier cas

Code :
  1. for my $hosts (@hosts) {
  2.    my $pid = fork;
  3.    if ($pid == 0) {
  4.        &kill-me($pid);
  5.    }
  6. }
  7. sub kill-me {
  8.    my $pid = shift;
  9.    kill 9, $pid;
  10. }




 
 
En fait peut importe comment on tue le fils, tu peux envoyer un signal ou bien lui demander de faire ça lui même.
 
Dans mon cas, je gère effectivement les timeout des fils en envoyant des signaux de fin, mais là c'est dans le cas ou par exemple la connexion ssh plante, pour ne pas lancer les commandes suivantes de copies de fichier.
Dans ce cas le père ne peut pas savoir le statut de la commande, donc c'est au fils de se terminer, d'où le die.
 
Exemple :

Code :
  1. $scp = Net::SCP->new("$host", "user" ) or die $scp->{errstr};
  2. $scp->get("/tmp/mylist.tmp","$inventaire" ) or $scp->{errstr};


 

gilou a écrit :


Je ne sais pas trop ce que signifie

Code :
  1. if ($pid == 0) {
  2.  sub kill-me {
  3.   die;
  4.  }


car habituellement, on ne définit pas un sub à l'intérieur d'une autre procédure.
Le fils meurt et pas le père? bizarre.
A+,


 
Justement c'est ça qui le chagrine, si je ne définie pas le sub à l'intérieur de la procédure contenant le "if $pid == 0", ce n'est pas le fils qui meurt, mais le père.
Dans le cas où j'ai 150 serveurs à traiter c'est gênant, car dès qu'une connexion échoue, je dois tout recommencer.
 
Le problème n'est pas handicapant outre mesure car en mettant les subs a l'intérieur du code du fils ça fonctionne mais je préférerais déclarer mes subs ailleurs..
 
Pour le peu que je connais du fork, il me semblait que le code était dupliqué :
- Est-ce tout le code ou juste le code dans lequel on définit "if $pid==0" ?
- Est-ce possible que le fils appelle la fonction du père plutôt que de dupliquer le code ?


Message édité par bichtoubard le 19-06-2009 à 09:27:43
Reply

Marsh Posté le 19-06-2009 à 18:56:45    

Comme je code en java ces temps ci, je n'avais pas les idées nettes.
 
Je procéderais ainsi:
 

Code :
  1. #/usr/bin/perl
  2.  
  3. my $father = $$;
  4.  
  5. for my $host (1..6) {
  6.    if ($$ == $father) { #si on veut éviter que les fils ne forkent eux aussi
  7.        fork;
  8.    }
  9. }
  10. &byebye();
  11.  
  12. sub byebye {
  13.    if ($$ != $father) {
  14.        exit(0); #ou die, qui est plus verbeux
  15.    }
  16. }


Ici, byebye est une fonction commune, qui ne tuera que les fils
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-06-2009 à 19:29:27    

Noter aussi qu'on peut passer par un pointeur de fonction:
 

Code :
  1. #/usr/bin/perl
  2.  
  3. sub do_nothing {}
  4. sub do_exit {exit(0);}
  5. my $functionref = \&do_nothing;
  6.  
  7. for my $host (1..3) {
  8.        my $pid = fork;
  9.        if ($pid == 0) {
  10.            $functionref = \&do_exit;
  11.        }
  12. }
  13.  
  14. &$functionref();


Noter qu'ici, je n'ai pas mis le code qui évite au fils de forker, pour plus de clarté.
&$functionref() sera un appel a do_nothing dans le père et a do_exit dans les fils.
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed