gestion des signaux

Le
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
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
espie
Le #21558311
In article 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 ?



Je ne comprend pas du tout ce que tu essaies de faire, exemple trop simplifie
je crains.

Que ton signal interrompe sleep, c'est parfaitement normal et attendu.

En plus, tu as un fork qui traine. Ca complique encore un peu, vu que tous
les process vont voir le ^Z.
Benoit Izac
Le #21558431
Bonjour,

le 15/04/2010 à 00:38, Marc Espie a écrit dans le message

Je ne comprend pas du tout ce que tu essaies de faire, exemple trop simplifie
je crains.

Que ton signal interrompe sleep, c'est parfaitement normal et attendu.

En plus, tu as un fork qui traine. Ca complique encore un peu, vu que tous
les process vont voir le ^Z.



Un exemple concret :
% cat test.pl
#!/usr/bin/perl
use strict;
use warnings;
$SIG{TSTP} = sub { print "signal receivedn"; };
while (1) {
my $pid = fork;
if (not defined $pid) {
die "fork failed";
} elsif ($pid eq 0) {
print time . "n";
exit;
} else {
sleep 5;
}
}
% perl test.pl
1271286741
1271286746
^Zsignal received
1271286747
^Zsignal received
1271286748
^C
%

Si je remplace
$SIG{TSTP} = sub { print "signal receivedn"; };
par
$SIG{TSTP} = 'IGNORE';
^Z n'a aucun effet. Ce que je souhaiterai, c'est la combinaison des
deux : ^Z lance l'exécution de « print "signal receivedn"; » mais est
ignoré par le reste du programme.

--
Benoit Izac
espie
Le #21559571
In article Benoit Izac
Si je remplace
$SIG{TSTP} = sub { print "signal receivedn"; };
par
$SIG{TSTP} = 'IGNORE';
^Z n'a aucun effet. Ce que je souhaiterai, c'est la combinaison des
deux : ^Z lance l'exécution de « print "signal receivedn"; » mais est
ignoré par le reste du programme.



Okay. C'est pas possible. SIGTSTP reste un signal. Et, sur ton systeme, ton
sleep est implemente en utilisant pause, qui va etre interrompu par les
signaux. Pour obtenir le resultat voulu, il faudra donc que tu remplaces
ton sleep par un truc plus complexe, qui note l'heure, qui fasse le sleep,
regarde comment celui-ci s'est fini, et en fasse un 2e si un TSTP est
passe par la... tu as peut-etre envie de regarder du cote de Time::HiRes
pour pouvoir faire des choses precises de ce cote-la.

Dans les cas pratiques que je connais, le fait qu'un signal interrompe
sleep n'est pas genant.

ton exemple jouet ne m'explique toujours pas pourquoi ca te gene pour
l'application que tu envisages. sans savoir ce que tu veux reellement faire,
c'est impossible de te conseiller une architecture plus adaptee...

Nota: tu as aussi une race condition dans ton exemple, mais peu visible vu
la brievete de tes process fils. Si tu tapes ^Z pile-poil au bon moment, tes
deux process vont le voir... et tu auras deux fois "signal received".
Alain Ketterlin
Le #21559701
(Marc Espie) writes:

In article Benoit Izac
Si je remplace
$SIG{TSTP} = sub { print "signal receivedn"; };
par
$SIG{TSTP} = 'IGNORE';
^Z n'a aucun effet. Ce que je souhaiterai, c'est la combinaison des
deux : ^Z lance l'exécution de « print "signal receivedn";  » mais est
ignoré par le reste du programme.



Okay. C'est pas possible. SIGTSTP reste un signal. Et, sur ton systeme, t on
sleep est implemente en utilisant pause, qui va etre interrompu par les
signaux. Pour obtenir le resultat voulu, il faudra donc que tu remplaces
ton sleep par un truc plus complexe, qui note l'heure, qui fasse le sleep,
regarde comment celui-ci s'est fini, et en fasse un 2e si un TSTP est
passe par la...



sleep renvoie tout ce qu'il faut pour pouvoir le relancer s'il est
interrompu.

-- Alain.
Benoit Izac
Le #21559871
Bonjour,

le 15/04/2010 à 09:34, Marc Espie a écrit dans le message

Si je remplace
$SIG{TSTP} = sub { print "signal receivedn"; };
par
$SIG{TSTP} = 'IGNORE';
^Z n'a aucun effet. Ce que je souhaiterai, c'est la combinaison des
deux : ^Z lance l'exécution de « print "signal receivedn"; » mais est
ignoré par le reste du programme.



Okay. C'est pas possible. SIGTSTP reste un signal. Et, sur ton systeme, ton
sleep est implemente en utilisant pause, qui va etre interrompu par les
signaux. Pour obtenir le resultat voulu, il faudra donc que tu remplaces
ton sleep par un truc plus complexe, qui note l'heure, qui fasse le sleep,
regarde comment celui-ci s'est fini, et en fasse un 2e si un TSTP est
passe par la... tu as peut-etre envie de regarder du cote de Time::HiRes
pour pouvoir faire des choses precises de ce cote-la.

Dans les cas pratiques que je connais, le fait qu'un signal interrompe
sleep n'est pas genant.

ton exemple jouet ne m'explique toujours pas pourquoi ca te gene pour
l'application que tu envisages. sans savoir ce que tu veux reellement faire,
c'est impossible de te conseiller une architecture plus adaptee...



En fait, le fils récupère des données et remplit un fichier RRD et je
veux produire le graphique en envoyant un signal. Ce n'est effectivement
pas dramatique que la base soit mises à jour à deux secondes
d'intervalles au lieu de cinq.

Mon réel problème c'est (était) juste de comprendre pourquoi ça ne fait
pas ce que je souhaite.

Nota: tu as aussi une race condition dans ton exemple, mais peu visible vu
la brievete de tes process fils. Si tu tapes ^Z pile-poil au bon moment, tes
deux process vont le voir... et tu auras deux fois "signal received".



Là, il me suffit d'ajouter « $SIG{TSTP} = 'IGNORE'; » dans le fils.

--
Benoit Izac
Benoit Izac
Le #21559961
Bonjour,

le 15/04/2010 à 10:03, Alain Ketterlin a écrit dans le message

Okay. C'est pas possible. SIGTSTP reste un signal. Et, sur ton systeme, ton
sleep est implemente en utilisant pause, qui va etre interrompu par les
signaux. Pour obtenir le resultat voulu, il faudra donc que tu remplaces
ton sleep par un truc plus complexe, qui note l'heure, qui fasse le sleep,
regarde comment celui-ci s'est fini, et en fasse un 2e si un TSTP est
passe par la...



sleep renvoie tout ce qu'il faut pour pouvoir le relancer s'il est
interrompu.



Effectivement, je n'avais jamais remarqué cela.

--
Benoit Izac
espie
Le #21560101
In article Benoit Izac
Nota: tu as aussi une race condition dans ton exemple, mais peu visible vu
la brievete de tes process fils. Si tu tapes ^Z pile-poil au bon moment, tes
deux process vont le voir... et tu auras deux fois "signal received".



Là, il me suffit d'ajouter « $SIG{TSTP} = 'IGNORE'; » dans le fils.



Non, tu vas reduire la race condition, mais pas la supprimer ;-)
entre le fork() et le $SIG{TSTP} = 'IGNORE', tu as toujours la race
condition.

La seule vraie facon de corriger ca pour de bon, c'est de bloquer/debloquer
les signaux autour du fork. Confere POSIX.
Benoit Izac
Le #21560461
Bonjour,

le 15/04/2010 à 11:07, Marc Espie a écrit dans le message

Nota: tu as aussi une race condition dans ton exemple, mais peu
visible vu la brievete de tes process fils. Si tu tapes ^Z pile-poil
au bon moment, tes deux process vont le voir... et tu auras deux
fois "signal received".



Là, il me suffit d'ajouter « $SIG{TSTP} = 'IGNORE'; » dans le fils.



Non, tu vas reduire la race condition, mais pas la supprimer ;-)
entre le fork() et le $SIG{TSTP} = 'IGNORE', tu as toujours la race
condition.

La seule vraie facon de corriger ca pour de bon, c'est de
bloquer/debloquer les signaux autour du fork. Confere POSIX.



Tu as raison. Je vais arrêter de bidouiller et ouvrir mon Stevens&Rago.

--
Benoit Izac
Alain Ketterlin
Le #21560451
Benoit Izac
En fait, le fils récupère des données et remplit un fichie r RRD et je
veux produire le graphique en envoyant un signal. Ce n'est effectivement
pas dramatique que la base soit mises à jour à deux secondes
d'intervalles au lieu de cinq.



Juste au cas où... : t'es sûr que le signal est la bonne solution ? Ton
fils risque d'écraser le fichier avant que le père l'ait lu compl ètement
(théoriquement au moins). Un bête pipe te fournirait la communica tion et
la synchronisation.

-- Alain.
Benoit Izac
Le #21560601
Bonjour,

le 15/04/2010 à 11:58, Alain Ketterlin a écrit dans le message

En fait, le fils récupère des données et remplit un fichier RRD et je
veux produire le graphique en envoyant un signal. Ce n'est effectivement
pas dramatique que la base soit mises à jour à deux secondes
d'intervalles au lieu de cinq.



Juste au cas où... : t'es sûr que le signal est la bonne solution ?



Absolument pas, c'est juste ce qui la première idée que j'ai eu en
écrivant le code et je n'ai vraiment pas réfléchi à tous les problèmes
que ça pouvait engendrer. Mais comme dit le proverbe, « c'est en
forgeant que l'on devient forgeron ».

Ton fils risque d'écraser le fichier avant que le père l'ait lu
complètement (théoriquement au moins). Un bête pipe te fournirait la
communication et la synchronisation.



Là, je ne sais pas comment se comporte rrdtool si un RRDs::update se
fait en même temps qu'un RRDs::graph ; j'ose espéré que ça a été conçu
pour mais il faudra quand même que je jette oeil dessus.

Bon, après, il faut quand même dire que ce code n'est pas de très grande
importance. Il n'est pas destiné à être diffusé et ne doit servir qu'à
monitorer la charge/décharge de ma batterie qui me semble plus que
fatiguée.

Le but second étant de me remettre à Perl que j'ai un peu délaissé ces
derniers temps. Je me rends compte au fur et à mesure que dès qu'on sort
des sentiers battus, ça demande des connaissances sur beaucoup de choses
et j'espérais que Perl s'en occuperait pour moi. Je crois qu'il est
temps que je me plonge dans tous les parties avancées de la
programmation système que j'avais jusqu'ici laissées de coté.

--
Benoit Izac
Publicité
Poster une réponse
Anonyme