+1 a Greg Hewgill para dirigir mi proceso de pensamiento en la dirección correcta para encontrar la respuesta.
El verdadero motivo de SIGPIPE
en ambos sockets y tuberías es el idioma/patrón de filtro que se aplica a las E/S típicas en los sistemas Unix.
Comenzando con las tuberías. Los programas de filtro como grep normalmente escriben en STDOUT
y leen desde STDIN
, que pueden ser redirigidos por el shell a una tubería. Por ejemplo:
cat someVeryBigFile | grep foo | doSomeThingErrorProne
La cáscara cuando se bifurca y luego de estos programas exec probablemente utiliza la llamada dup2
sistema para redirigir STDIN
, STDOUT
y STDERR
a los tubos apropiados.
Como el programa de filtro grep
no sabe y no tiene forma de saber que su salida ha sido redirigida, la única forma de decirle que deje de escribir en una tubería rota si doSomeThingErrorProne
falla es con una señal desde los valores de retorno de escribe a STDOUT
rara vez se comprueban.
El análogo con sockets sería el servidor inetd
tomando el lugar del shell.
Como ejemplo, supongo que puede convertir grep
en un servicio de red que opera en sockets TCP
. Por ejemplo, con inetd
si usted quiere tener un servidor grep
en TCP
puerto 8000 y luego añadir esto a /etc/services
:
grep 8000/tcp # grep server
A continuación, añadir esto a /etc/inetd.conf
:
grep stream tcp nowait root /usr/bin/grep grep foo
Enviar SIGHUP
a inetd
y conectarse al puerto 8000 con telnet. Esto debería causar inetd
para tenedor, duplicar el socket en STDIN
, STDOUT
y STDERR
y luego ejecutar grep
con foo como argumento. Si comienza a escribir líneas en telnet grep
hará eco de esas líneas que contienen foo.
Ahora reemplace telnet con un programa llamado ticker
que, por ejemplo, escribe una secuencia de cotizaciones de acciones en tiempo real en STDOUT
y obtiene comandos en STDIN
.Alguien hace telnets al puerto 8000 y escribe "start java" para obtener presupuestos para Sun Microsystems. Luego se levantan y van a almorzar. telnet inexplicablemente se cuelga. Si no hubiera SIGPIPE
para enviar, entonces ticker
seguiría enviando cotizaciones para siempre, sin saber que el proceso en el otro extremo se había estrellado, y desperdiciando innecesariamente los recursos del sistema.
Hay algo más que sucede aquí que es bastante sutil: una conexión TCP puede estar medio cerrada, lo que significa que un lado ha cerrado el socket (enviado un paquete FIN), pero el otro lado todavía tiene datos para enviar. Si va a rooting en este nivel, lea: http://superuser.com/questions/298919/what-is-tcp-half-open-connection-and-tcp-half-closed-connection – rbp