> Tech > Traitement d’erreurs avec des timeouts

Traitement d’erreurs avec des timeouts

Tech - Par iTPro - Publié le 24 juin 2010
email

Pour ce qui est des erreurs logicielles, presque toutes sont signalisées dans errno. Si vous essayez de vous connecter à un port non associé à une application, le système d’exploitation de cet ordinateur détecte l’anomalie et peut envoyer un message d’erreur à votre ordinateur pour l’en informer. Mais, que se

passe-t-il si le câble du réseau est sectionné ou si le courant est coupé ? Si l’alimentation Internet présente un problème ? Ce genre de défaillances matérielles empêche de recevoir des messages d’erreur explicatifs.

Par conséquent, je vous incite vivement à limiter le temps pendant lequel vous êtes disposé à attendre une réponse d’un autre programme. Ecrivez le code de telle sorte que si aucune donnée ne vient par le socket pendant une longue période, votre logiciel déclenche un timeout et récupère en bon ordre.

Les temporisations peuvent être traitées de deux manières dans la programmation par sockets. La première consiste à demander au système d’exploitation qu’il envoie un signal après un certain laps de temps et la seconde consiste à utiliser l’API select() pour attendre que les données arrivent sur un socket. La méthode du signal me paraît plus simple, donc je la décris dans cet article. L’autre méthode est décrite dans l’article « La temporisation appliquée aux sockets » (iSeries News octobre 2004 ou www.itpro.fr Club abonnés).

Un signal est un message qui peut être envoyé pour interrompre votre programme au milieu de son traitement. Pour utiliser des signaux, définissez une sous-procédure appelée « gestionnaire de signal ». Quand le signal est délivré, votre programme s’arrête et le gestionnaire de signal est exécuté. Quand le gestionnaire a terminé, votre programme reprend son exécution au point d’interruption.

Comme le gestionnaire de signal est une sous-procédure que vous pouvez coder vous-mêmes, vous pouvez écrire le traitement qu’entraînera la réception d’un signal. Mais ce n’est pas utile pour les besoins de cet exemple. L’une des propriétés utiles des API sockets est qu’elles sont interrompues chaque fois qu’un signal est reçu. Par conséquent, tout ce qui est nécessaire pour mettre une API en timeout est d’envoyer un signal au moment opportun.

La figure 9 montre une sous-procédure appelée init_signals() qui configure une sous-procédure appelée got_ alarm() comme gestionnaire de signal pour le signal appelé SIGALRM. Pour cela, elle crée d’abord une structure de données appelée act, de même format que la structure de données sigaction_t que j’ai définie dans le membre SIGNAL_H /copy. Dans cette structure de données, elle définit la sousprocédure got_alarm() comme le gestionnaire de signal et ordonne au système de bloquer tous les signaux pendant que got_alarm() s’exécute (en A, figure 9). Elle appelle ensuite l’API sigaction() et transmet cette structure de données comme un paramètre, ainsi que la constante SIGALRM qui indique quel signal devrait être traité (en B).

Une fois que cette sous-procédure init_signals() a été appelée, tout signal SIGALRM reçu par le job a pour effet de stopper l’action du programme, d’appeler la sous-procédure got_alarm(), puis de continuer là où il s’est interrompu.

Tout cela étant en place, je peux maintenant utiliser le signal SIGALRM pour appliquer le timeout à mes API sockets. La figure 10 montre une sous-procédure appelée tconnect() qui connecte un socket avec un timeout. J’ai donné à tconnect() presque les mêmes paramètres qu’à l’API connect(), donc quand vous serez familiarisés avec l’API connect(), il sera très facile d’appeler tconnect(). Le seul paramètre supplémentaire de tconnect() spécifie le nombre de secondes pendant lequel on essaie de se connecter avant d’abandonner.

L’API alarm() ordonne au système d’exploitation d’envoyer le signal SIGALRM à ce programme après un certain nombre de secondes. Par exemple, si la variable timeout est mise à 10, l’OS envoie un signal SIGALRM après 10 secondes. J’appelle cette API juste avant d’appeler l’API connect (A en figure 10). Si, après le délai de 10 secondes, le programme est encore en train d’attendre que l’API connect() se termine, le signal est reçu et l’API connect() renvoie -1. Quand vous consultez errno, il est à 3407, qui signifie « interrompu par signal ». J’ai aussi une constante nommée dans le copy book ERRNO_H appelée EINTR qui est mise à 3407. Donc, si connect() échoue et si errno=EINTR, cela indique que le timeout a été appliqué à la connexion.

Après avoir appelé connect(), j’appelle l’API alarm() avec un paramètre de 0 (B en figure 10). Si connect() n’a pas eu de time out et s’est terminé avant que SIGALRM soit envoyé au programme, cela l’annule afin que le signal ne soit jamais délivré. De sorte que je ne risque par d’annuler par mégarde une API différente.

Téléchargez gratuitement cette ressource

TOP 5 Modernisation & Sécurité des Postes Clients

TOP 5 Modernisation & Sécurité des Postes Clients

Pour aider les entreprises à allier les restrictions liées à la crise et la nécessaire modernisation de leurs outils pour gagner en réactivité, souplesse et sécurité, DIB-France lance une nouvelle offre « Cloud-In-One » combinant simplement IaaS et DaaS dans le Cloud, de façon augmentée.

Tech - Par iTPro - Publié le 24 juin 2010