OVH Cloud OVH Cloud

$SIG{ALRM} et $s->can_read

8 réponses
Avatar
Sébastien Cottalorda
Salut à tous,

Mon système:
Mandrake 10.1 (kernel 2.6.8.1-12 - Perl 5.8.5-3)

J'ai fait un programme qui fait ceci:

Il se connecte sur un serveur TCP, et écoute ce qu'on lui envoie jusqu'à
ce qu'il reçoive un caractère spécial qui lui indique la fin du message.
A partir de ce message, il effectue un tratement, puis il répond au serveur.
Cependant, aléatoirement, il peut être succeptible d'envoyer, à sa
propre initiative, via la socket, des informations au serveur.

Voici le squelette de mon programme:


use IO::Socket;
use IO::Select;

...
Création de la socket et connexion au serveur
$SIG{ALRM}= sub { &envoiealeatoire()}
alarm(5);
LOOP: Boucle sans fin
RECEP: Boucle sans fin
Sortie de la boucle sur réception grace
à $s->can_read(10)
FINRECEP
Traitement de la réponse
Envoie au serveur la réponse
FINLOOP

sub envoiealeatoire{
alarm 0;
Envoie via la socket d'un message au serveur.
alarm aléatoire.
}


Mon problème est le suivant:
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm
du module Time::HiRes), il la traite en envoyant, via la socket, un
message, mais dès qu'il fini ce traitement, le programme reprend son
execution APRES le $s->can_read(10)
Tout se passe comme si je venais alors de recevoir quelque chose, sur la
socket, mais rien.
Y a t'il une explication ?

Merci de votre aide.

Sébastien

8 réponses

Avatar
Paul Gaborit
À (at) Fri, 22 Jul 2005 15:03:04 +0200,
Sébastien Cottalorda écrivait (wrote):
[...]
lorsque le programme reçoit l'interruption de alarm (en fait de ualarm
du module Time::HiRes), il la traite en envoyant, via la socket, un
message, mais dès qu'il fini ce traitement, le programme reprend son
execution APRES le $s->can_read(10)
Tout se passe comme si je venais alors de recevoir quelque chose, sur
la socket, mais rien.
Y a t'il une explication ?


Oui. Votre instruction d'attente a été interrompue par un signal (ici
le SIGALARM). C'est le comportement normal.

Par ailleurs, il faut minimiser le plus possible la quantité de code
dans un handler de signal. L'idéal : juste changer la valeur d'une
variable.

Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux
effets. Effet direct : positionner un flag à 1. Effet indirect:
interrompre l'attente. En sortie de lecture, vous testez le flag. Si
il est à un 1 vous déclencher votre action d'envoi, vous remettez le
flag à zéro. et vous reprenez l'attente. Sinon, vous faites le
traitement normal.

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

Avatar
Sébastien Cottalorda
À (at) Fri, 22 Jul 2005 15:03:04 +0200,
Sébastien Cottalorda écrivait (wrote):
[...]

lorsque le programme reçoit l'interruption de alarm (en fait de ualarm
du module Time::HiRes), il la traite en envoyant, via la socket, un
message, mais dès qu'il fini ce traitement, le programme reprend son
execution APRES le $s->can_read(10)
Tout se passe comme si je venais alors de recevoir quelque chose, sur
la socket, mais rien.
Y a t'il une explication ?



Oui. Votre instruction d'attente a été interrompue par un signal (ici
le SIGALARM). C'est le comportement normal.


En effet.

Par ailleurs, il faut minimiser le plus possible la quantité de code
dans un handler de signal. L'idéal : juste changer la valeur d'une
variable.

Dans votre cas, en utilisant tout cela, le SIGALARM aurait deux
effets. Effet direct : positionner un flag à 1. Effet indirect:
interrompre l'attente. En sortie de lecture, vous testez le flag. Si
il est à un 1 vous déclencher votre action d'envoi, vous remettez le
flag à zéro. et vous reprenez l'attente. Sinon, vous faites le
traitement normal.



Effectivement, cela me semble parfaitement jouable.

Le fait de ralentir le traitement du handler de signal par l'envoi d'un
message via socket peut aussi avoir un effet pervers, dans la mesure où
l'envoi peut générer une attente et donc figer le programme jusqu'à se
que cela finisse.

Merci beaucoup.

Sébastien


Avatar
Paul Gaborit
À (at) Fri, 22 Jul 2005 15:59:28 +0200,
Sébastien Cottalorda écrivait (wrote):
Le fait de ralentir le traitement du handler de signal par l'envoi
d'un message via socket peut aussi avoir un effet pervers, dans la
mesure où l'envoi peut générer une attente et donc figer le programme
jusqu'à se que cela finisse.


Certes... Le véritable problème est l'interblocage (ou «étreinte
mortelle» ou «deadlock») :

Le serveur envoie des données mais votre client décide (avant lire
ce que lui envoie le serveur) d'envoyer lui aussi des données au
serveur... qui ne les lit pas car il attend que votre client ait
fini de lire. Résultat : blocage...

Il faut (au minimum) que l'un des deux programmes soient écrit avec
des lectures/écritures non-bloquantes pour éviter ce problème
classique de communication bi-directionnelle.

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

Avatar
Sébastien Cottalorda
À (at) Fri, 22 Jul 2005 15:59:28 +0200,
Sébastien Cottalorda écrivait (wrote):

Le fait de ralentir le traitement du handler de signal par l'envoi
d'un message via socket peut aussi avoir un effet pervers, dans la
mesure où l'envoi peut générer une attente et donc figer le programme
jusqu'à se que cela finisse.



Certes... Le véritable problème est l'interblocage (ou «étreinte
mortelle» ou «deadlock») :

Le serveur envoie des données mais votre client décide (avant lire
ce que lui envoie le serveur) d'envoyer lui aussi des données au
serveur... qui ne les lit pas car il attend que votre client ait
fini de lire. Résultat : blocage...

Il faut (au minimum) que l'un des deux programmes soient écrit avec
des lectures/écritures non-bloquantes pour éviter ce problème
classique de communication bi-directionnelle.

C'est heureusement le cas de mon programme serveur.


Je viens de faire la modif, j'arrive à traiter correctement mon
problème, même avec un ualarm de 10000 µs (pas la peine de descendre
plus bas, je n'en ai pas l'utilité).

Mon programme serveur encaisse alors plus de 3 x 100 requêtes à la
seconde. Analyse chacune d'elles au niveau syntaxique, et aiguille
chaque trame vers le bon client en fonction de certains critères.

Mon programme fait partie d'un projet d'application de Contrôle d'Accès
de véhicule dans un parking.
Jamais je n'aurais penser aller aussi vite.

Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.
En ce qui me concerne, une réponse de cette envergure me convient tout a
fait.

Merci encore pour votre aide.

Sébastien


Avatar
Paul Gaborit
À (at) Fri, 22 Jul 2005 16:39:51 +0200,
Sébastien Cottalorda écrivait (wrote):
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.


Qui a bien pu vous faire croire ça ? ;-) La bonne définition du
« temps réel » est « garantir un temps de réponse compatible avec
le besoin ».

En ce qui me concerne, une réponse de cette envergure me convient tout
a fait.


C'est donc bien que Perl, dans les cas de votre application, peut
faire du temps réel... ;-)

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

Avatar
Sébastien Cottalorda
Paul Gaborit wrote:


À (at) Fri, 22 Jul 2005 16:39:51 +0200,
Sébastien Cottalorda écrivait (wrote):
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.


Qui a bien pu vous faire croire ça ? ;-) La bonne définition du
« temps réel » est « garantir un temps de réponse compatible avec
le besoin ».


voir dans les FAQ de perl "Quand ne pas utiliser Perl :"...

En ce qui me concerne, une réponse de cette envergure me convient tout
a fait.


C'est donc bien que Perl, dans les cas de votre application, peut
faire du temps réel... ;-)



J'en suis à présent convaincu.

--
[ retirer NOSPAM pour répondre directement
remove NOSPAM to reply directly ]


Avatar
Paul Gaborit
À (at) Fri, 22 Jul 2005 17:29:09 +0200,
Sébastien Cottalorda écrivait (wrote):
Paul Gaborit wrote:
À (at) Fri, 22 Jul 2005 16:39:51 +0200,
Sébastien Cottalorda écrivait (wrote):
Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.


Qui a bien pu vous faire croire ça ? ;-) La bonne définition du
« temps réel » est « garantir un temps de réponse compatible avec
le besoin ».


voir dans les FAQ de perl "Quand ne pas utiliser Perl :"...


Je cite : « ... Perl n'est probablement pas bien adapté pour des
systèmes embarqués temps-réel,...».

Il y a deux nuances ici :

1- "pas bien adapté" ne veut pas dire "inutilisable" ;-)

2- "systèmes embarqués temps-réel". Pour moi le plus important est le
terme "embarqués" qui implique (souvent) une fiabilité garantie...

De toutes manières, la plupart des Unix ne sont pas réellement adaptés
au vrai temps-réel. Par exemple, il est toujours possible
d'interrompre (momentanément) une tâche quelconque comme par exemple
la lecture d'un film ou d'un fichier audio rien qu'en lançant une
bonne grosse compilation (qui monopolise la ressource critique qui
dans ce cas est le disque). On peut s'en sortir en gérant finement les
priorités ou en utilisant des noyaux bien conçus mais ce n'est pas
garanti à la base...

Bon. D'accord ! Je pousse le bouchon un peu loin ;-)

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



Avatar
Sébastien Cottalorda
À (at) Fri, 22 Jul 2005 17:29:09 +0200,
Sébastien Cottalorda écrivait (wrote):

Paul Gaborit wrote:

À (at) Fri, 22 Jul 2005 16:39:51 +0200,
Sébastien Cottalorda écrivait (wrote):

Il faut croire que lorsqu'on dit que Perl n'est pas fait pour le temps
réel, ce doit être une question de temps < milliseconde.


Qui a bien pu vous faire croire ça ? ;-) La bonne définition du
« temps réel » est « garantir un temps de réponse compatible avec
le besoin ».


voir dans les FAQ de perl "Quand ne pas utiliser Perl :"...



Je cite : « ... Perl n'est probablement pas bien adapté pour des
systèmes embarqués temps-réel,...».


Ma traduction de l'anglais n'allait pas jusque là.
J'avais compris, "pas conseillé", "pas adapté".

Me vl'a rassuré définitivement.