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

gestion des signaux

15 réponses
Avatar
Benoit Izac
Bonjour,

J'ai un petit problème avec la gestions de signaux en Perl. J'ai écrit
un petit script qui ressemble à ça :

while (1) {
$pid = fork;
if (not defined $pid) {
# erreur
} elsif ($pid == 0) {
une_tache;
} else {
sleep 5;
}
}

Jusqu'ici, ça marche bien. Je souhaite rajouter un petit plus en envoyant
un signal et faire autre chose, ça ressemble à ça :

# TSTP est reçu lorsque je tape ^Z
$SIG{TSTP} = sub { autre_tache; };
# même programme que ci-dessus

autre_tache s'exécute bien lorsque je tape ^Z mais le problème c'est que
une_tache s'exécute aussi. Comment faire en sorte que ^Z puisse juste
exécuter autre_tache sans interférer sur le reste du programme ?

Merci.
--
Benoit Izac

5 réponses

1 2
Avatar
Benoit Izac
Grâce à vos remarque, Je crois que je suis arrivé à faire ce que je
voulais assez simplement. Je ne suis pas sûr pour la race condition mais
ça à l'air de fonctionner au poil. Commentaires bienvenus !

#!/usr/bin/perl
use strict;
use warnings;

while (1) {
$SIG{TSTP} = 'IGNORE'; # merci Marc !
my $pid = fork;
if (not defined $pid) {
die "fork failed";
} elsif ($pid eq 0) {
print time . "n";
exit;
} else {
$SIG{TSTP} = sub { print "signal receivedn"; };
my $t = 5;
do { $t -= sleep $t } while ($t); # merci Alain !
}
}

--
Benoit Izac
Avatar
Denis Dordoigne
Bonjour,

do { $t -= sleep $t } while ($t);


Je ne sais pas quel est ton OS, mais connaissant les surprises que l'on
peut avoir parfois avec la gestion des secondes, j'écrirais plutôt :
do { $t -= sleep $t } while ($t >= 0);

Sinon vu l'usage prévu il est improbable que 2 signaux soient reçus en 5
secondes, si c'était du code jetable j'écrirais carrément :
sleep($t - sleep $t);

Bonne continuation,

--
Denis Dordoigne
Membre de l'April - promouvoir et défendre le logiciel libre - april.org
Rejoignez maintenant plus de 5 000 personnes, associations,
entreprises et collectivités qui soutiennent notre action
Avatar
Benoit Izac
Dans le message , le 15/04/2010 à 22:44, j'ai
écrit :

Grâce à vos remarque, Je crois que je suis arrivé à faire ce que je
voulais assez simplement. Je ne suis pas sûr pour la race condition mais
ça à l'air de fonctionner au poil. Commentaires bienvenus !

#!/usr/bin/perl
use strict;
use warnings;

while (1) {
$SIG{TSTP} = 'IGNORE'; # merci Marc !
my $pid = fork;
if (not defined $pid) {
die "fork failed";
} elsif ($pid eq 0) {
print time . "n";
exit;
} else {
$SIG{TSTP} = sub { print "signal receivedn"; };
my $t = 5;
do { $t -= sleep $t } while ($t); # merci Alain !
}
}



Bon il y a quand même un petit problème avec le code ci-dessus : c'est
la fête des zombies !

Quelle est la meilleure façon de gérer les fils ?
* $SIG{CHLD} = 'IGNORE'; après le while (1)
* use POSIX ":sys_wait_h"; while (waitpid(-1, WNOHANG) > 0) {}
après le sleep (ou ailleurs ?)

--
Benoit Izac
Avatar
Benoit Izac
Bonjour,

le 16/04/2010 à 07:02, Denis Dordoigne a écrit dans le message
<4bc7ef49$0$23885$ :

do { $t -= sleep $t } while ($t);


Je ne sais pas quel est ton OS



Là c'est un Linux, mais ça pourrait-être n'importe quel OS de type Unix.

mais connaissant les surprises que l'on peut avoir parfois avec la
gestion des secondes, j'écrirais plutôt :
do { $t -= sleep $t } while ($t >= 0);



Je ne pense pas que ce soit nécessaire sur ma plateforme. Existe-t-il un
équivalent à assert(3) en Perl ?

Sinon vu l'usage prévu il est improbable que 2 signaux soient reçus en
5 secondes, si c'était du code jetable j'écrirais carrément :
sleep($t - sleep $t);



Oui mais là ça coûte pas bien cher de le faire plus ou moins
correctement. Il y aurait plusieurs dizaines de ligne de code je dis pas.

--
Benoit Izac
Avatar
espie
In article ,
Benoit Izac wrote:
Bon il y a quand même un petit problème avec le code ci-dessus : c'est
la fête des zombies !

Quelle est la meilleure façon de gérer les fils ?
* $SIG{CHLD} = 'IGNORE'; après le while (1)
* use POSIX ":sys_wait_h"; while (waitpid(-1, WNOHANG) > 0) {}
après le sleep (ou ailleurs ?)



il n'y a pas de meilleure facon. Si les deux sont possibles, c'est parce
qu'elles ont un usage different.

- si tu n'en as jamais rien a battre du statut de tes fils, alors
indubitablement, IGNORE sigchld.
- si au contraire tu veux t'assurer que tout s'est bien passe, il faut
au minimum enregistrer les pid dans un hash, faire le wait qui va bien,
et prendre une action appropriee.

De toutes facons, depuis le debut de ce thread, tes problemes ne sont
pas specifiques a perl. C'est entierement des soucis de design
d'application Unix...

Dans mon experience, il y a de bonnes chances que la vraie solution soit
de mettre tes besoins a plat, de reflechir a une architecture la plus simple
possible, et de reecrire une bonne partie de ton code.
1 2