308 votes

Comment prévenir les SIGPIPEs (ou les manipuler correctement)

J'ai un petit programme serveur qui accepte des connexions sur un réseau TCP ou local socket UNIX, lit simple commande, et en fonction de la commande, envoie une réponse. Le problème est que les clients n'ont pas d'intérêt dans la réponse parfois et les sorties tôt, donc, de l'écriture à cette prise, vous risquez de provoquer un signal SIGPIPE et faire de mon serveur crash. Quelle est la meilleure pratique pour éviter le crash ici? Est-il un moyen de vérifier si de l'autre côté de la ligne est encore en train de lire? (select() ne semble pas fonctionner ici comme il l'a toujours dit que le socket est accessible en écriture). Ou devrais-je attraper le signal SIGPIPE avec un gestionnaire et l'ignorer?

315voto

dvorak Points 9516

Généralement, vous définiriez le gestionnaire SIGPIPE à SIG_IGN si vous pensez que votre application va jamais écrire sur un socket/tuyau cassé. Il est généralement beaucoup plus facile de gérer l’erreur à l’écriture, que pour faire quelque chose d’intelligent dans un gestionnaire SIGPIPE.

168voto

user55807 Points 959

Une autre méthode consiste à modifier la prise afin qu’il génère jamais SIGPIPE sur write(). C’est plus pratique dans les bibliothèques, où vous ne pourriez pas vouloir un gestionnaire de signal global pour SIGPIPE.

Sur la plupart des systèmes, (en supposant que vous utilisez C/C++), vous pouvez faire cela avec :

Avec cela en effet, au lieu du signal SIGPIPE généré, EPIPE sera retourné.

124voto

sklnd Points 1746

Je suis super en retard à la fête, mais `` n’est pas portable et peuvent ne pas fonctionner sur votre système (il semble être une chose BSD).

Une alternative agréable si vous êtes sur, disons, un système de Linux sans serait de mettre la drapeau sur votre appel Send (2).

32voto

kroki Points 217

Dans ce post , j’ai décrit une solution possible pour Solaris cas lorsque ni SO_NOSIGPIPE ni MSG_NOSIGNAL est disponible.

23voto

Sam Points 13570

Poignée de signal SIGPIPE Localement

Il est généralement préférable de traiter l'erreur locale plutôt que dans un signal global gestionnaire d'événements depuis localement, vous aurez plus de contexte à ce qui se passe et quels sont les recours pour les prendre.

J'ai une couche de communication dans une de mes applications que permet mon appli de communiquer avec un accessoire externe. Lorsqu'une erreur d'écriture se produit-je le jeter et d'exception dans la couche de communication et de laisser la bulle jusqu'à un bloc try catch pour gérer.

Code:

Le code d'ignorer un SIGNAL de signal de sorte que vous pouvez le manipuler localement est:

// We expect write failures to occur but we want to handle them where 
// the error occurs rather than in a SIGPIPE handler.
signal(SIGPIPE, SIG_IGN);

Ce code permettra d'éviter le signal SIGPIPE d'être soulevées, mais vous obtiendrez une lecture / écriture d'erreur lorsque vous essayez d'utiliser la prise, de sorte que vous aurez besoin de vérifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X