+1 À Greg Hewgill pour diriger mon processus de pensée dans la bonne direction pour trouver la réponse.
La véritable raison de SIGPIPE
dans les sockets et les canalisations est l'idiome/modèle de filtre qui s'applique aux E/S typiques dans les systèmes Unix.
À partir de tubes. Les programmes de filtrage comme grep écrivent généralement à STDOUT
et lisent à partir de STDIN
, qui peuvent être redirigés par le shell vers un canal. Par exemple:
cat someVeryBigFile | grep foo | doSomeThingErrorProne
quand le réservoir fourches puis ces programmes de exec utilise probablement l'appel système dup2
à redirigent STDIN
, STDOUT
et STDERR
aux tuyaux appropriés. Puisque le programme de filtrage grep
ne sait pas et n'a aucun moyen de savoir que sa sortie a été redirigée alors la seule façon de lui dire d'arrêter d'écrire sur un tube rompu si doSomeThingErrorProne
se bloque avec un signal puisque les valeurs de retour de écrit au STDOUT
sont rarement vérifiées. L'analogue avec les sockets serait le serveur inetd
prenant la place de la coquille.
À titre d'exemple, je suppose que vous pouvez transformer grep
en un service réseau qui fonctionne sur TCP
sockets. Par exemple avec inetd
si vous voulez avoir un serveur grep
sur TCP
port 8000 puis l'ajouter à /etc/services
:
grep 8000/tcp # grep server
Puis ajoutez ceci /etc/inetd.conf
:
grep stream tcp nowait root /usr/bin/grep grep foo
Envoyer SIGHUP
-inetd
et se connecter au port 8000 avec telnet. Cela devrait provoquer inetd
à fork, dup la douille sur STDIN
, STDOUT
et STDERR
et ensuite exec grep
avec foo comme argument. Si vous commencez à taper des lignes dans telnet grep
fera écho aux lignes qui contiennent foo.
Remplacez maintenant telnet par un programme nommé ticker
qui écrit par exemple un flux de cotations boursières en temps réel à STDOUT
et obtient des commandes sur STDIN
.Quelqu'un se connecte au port 8000 et tape "start java" pour obtenir des devis pour Sun Microsystems. Puis ils se lèvent et vont déjeuner. telnet se bloque inexplicablement. S'il n'y avait aucun SIGPIPE
à envoyer alors ticker
continuerait à envoyer des citations pour toujours, ne sachant jamais que le processus à l'autre bout s'était écrasé, et gaspillant inutilement des ressources de système.
Il se passe ici quelque chose d'assez subtil: une connexion TCP peut être à moitié fermée, ce qui signifie qu'un côté a fermé le socket (envoyé un paquet FIN), mais que l'autre côté a encore des données à envoyer. Si vous allez à ce niveau, s'il vous plaît lisez: http://superuser.com/questions/298919/what-is-tcp-half-open-connection-and-tcp-half-closed-connection – rbp