Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[Parallel::ForkManager] La question qui tue

6 réponses
Avatar
Arthur
Bonjour,

Je suis actuellement dans l'impasse et j'en apelle aux lecteurs de ce
newsgroup car je ne vois vraiment pas comment faire.

Voil=E0 un r=E9sum=E9 de mon probl=E8me :
- je dois ex=E9cuter un script PHP tant que son code de retour est 0.
Pour aller plus vite, j'en ex=E9cute 5 en parall=E8le
- d=E8s que le code de retour d'un script PHP est diff=E9rent de 0,
j'arr=EAte l'ex=E9cution (en attendant bien s=FBr que les 4 autres se
terminent)
- pour cel=E0, j'utilise Parallel::ForkManager. Le bout de code suivant
marche presque, sauf qu'il m'est impossible d'arr=EAter l'execution.

///////////////// Code /////////////////

#!/usr/bin/perl -w
use lib '.';
use strict;
use Parallel::ForkManager;

my $max_procs =3D 5;
my $pm =3D new Parallel::ForkManager($max_procs);

my $continu =3D 1;
while($continu =3D=3D 1)
{
my $pid =3D $pm->start and next;

if($pid =3D=3D 0){
#code du fils
my $exit_code =3D system("php envoi.php");
print " f: ".$exit_code;
if($exit_code !=3D "0")
{
print " fini !";
$continu=3D0;
}
print "\n";
exit(0);
}
$pm->finish;
}

print " on attends les fils non finis";
$pm->wait_all_children;


///////////////// Fin Code /////////////////

Quelqu'un pourrait-il prendre deux minutes pour se pencher sur ce
probl=E8me ?

Merci d'avance

6 réponses

Avatar
damien guerin
fork réalise une copie de l'image mémoire du processus père pour
créer le processus fils...
Autrement dit quand il y en a un qui tombe sur continu=0, les autres
ont toujours leur continu à 1 (y compris ton père).

En lisant ton code, je pense que ton père boucle sans arret.
Avatar
Arthur
Oui, pour le père, continu est toujours à . Et c'est vrai que ça
parrait logique.
Mais voyez-vous comment je peux faire autrement ?

fork réalise une copie de l'image mémoire du processus père pour
créer le processus fils...
Autrement dit quand il y en a un qui tombe sur continu=0, les autres
ont toujours leur continu à 1 (y compris ton père).

En lisant ton code, je pense que ton père boucle sans arret.


Avatar
damien guerin
Solution de merde :
ton fils qui tombe sur le continu=0, tu crée un fichier...
Le parent test régulièrement l'existance de ce fichier. S'il le
trouve, il s'arret.

Solution plus "pro" :
utilisation des sémaphores (mémoire partagé) pour partager ta
variable "continu"

Y a peut être d'autres solutions plus sympas mais sans trop
réfléchir trouve au moins celles là ;)
Avatar
damien guerin
Ah oui, y a aussi possibilité d'utiliser des signaux... Bref, tu as le
choix je pense. Bon il est vrai que la solution de merde proposée est
plus rapide et plus simple que les deux autres, après ça depend de
toi.
Avatar
Paul Gaborit
À (at) 14 Jun 2005 06:17:25 -0700,
"Arthur" écrivait (wrote):
Voilà un résumé de mon problème :
- je dois exécuter un script PHP tant que son code de retour est 0.
Pour aller plus vite, j'en exécute 5 en parallèle
- dès que le code de retour d'un script PHP est différent de 0,
j'arrête l'exécution (en attendant bien sûr que les 4 autres se
terminent)
- pour celà, j'utilise Parallel::ForkManager. Le bout de code suivant
marche presque, sauf qu'il m'est impossible d'arrêter l'execution.


Tel que spécifié, votre problème ne peut pas se parallèliser puisqu'une tâche
ne doit être lancée que lorsque la précédente retourne 0... Supposons que ce
soit tout de même ce que vous voulez faire.

Pourquoi ne vous inspirez-vous pas des exemples de la doc de
Parallel::ForkManager ?

------------------------------------------------------------
use strict;
use Parallel::ForkManager;

my $continue = 1;
my $max_procs = 5; # n'autorise en fait que 4 fils !
my $pm = new Parallel::ForkManager($max_procs);

# fonction appelée par le père à la fin de chaque fils
$pm->run_on_finish(
sub {
my ($pid, $exit_code, $num_sub) = @_;
print "** $num_sub just got out of the pool ".
"with PID $pid and exit code: $exit_coden";
# c'est la qu'on sait si on doit s'arreter
$continue = 0 if ($exit_code != 0);
}
);

# Juste pour voir quand on attend...
$pm->run_on_wait(
sub {
print "** Have to wait for one children ...n"
},
0.5
);

my $num_sub = 0;
while ($continue) {
$num_sub++;
my $pid = $pm->start($num_sub) and next;
# un 'exec' sera plus rapide que de passer par 'system' (*)
exec "php envoi.ph";
}

print "Waiting for Children...n";
$pm->wait_all_children;
print "Everybody is out of the pool!n";
------------------------------------------------------------

Je vous laisse le soin de traduire les messages à votre sauce...

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Eriam Schaffter
Ah oui, y a aussi possibilité d'utiliser des signaux... Bref, tu as le
choix je pense. Bon il est vrai que la solution de merde proposée est
plus rapide et plus simple que les deux autres, après ça depend de
toi.



ca peut etre sympa d'utiliser POE pour ce genre d'automatismes :)

moi j'aime bien