¿Qué causa el error de tubería rota?

84

Sé que se produce un error de tubería rota cuando el enchufe del lado del par está cerrado.

Pero, en mi prueba, noté que una llamada de 'enviar' inmediata en este lado cuando el lado del par está cerrado no siempre conduce a un error de tubería rota.

P.ej:

Después de cerrar el socket en el lado del par (he intentado un cierre limpio llamando close y también un cierre anormal al matar al par), si trato de enviar 40 bytes, entonces no obtengo una tubería rota, pero, si trato de envía 40000 bytes y luego inmediatamente da un error de tubería rota.

¿Qué causa exactamente la rotura de la tubería y se puede predecir su comportamiento?

Arrendajo
fuente

Respuestas:

59

Puede llevar tiempo observar el cierre de la red; el tiempo total es nominalmente de unos 2 minutos (¡sí, minutos!) Después de un cierre antes de que se asuma que todos los paquetes destinados al puerto están muertos. La condición de error se detecta en algún momento. Con una pequeña escritura, está dentro de la MTU del sistema, por lo que el mensaje se pone en cola para su envío. Con una escritura grande, eres más grande que la MTU y el sistema detecta el problema más rápido. Si ignora la señal SIGPIPE, las funciones devolverán el error EPIPE en una tubería rota, en algún momento cuando se detecte la rotura de la conexión.

Jonathan Leffler
fuente
4
@varevarao: No creo que poner en cola las transmisiones y enviarlas a intervalos específicos sea una solución. Poner en cola las transmisiones hasta que haya más de la MTU para enviar puede ser una solución alternativa si su aplicación puede soportar los retrasos.
Jonathan Leffler
11

El estado actual de un socket está determinado por la actividad de "mantener vivo". En su caso, es posible que cuando esté emitiendo la sendllamada, la keep-aliveactividad le diga que el socket está activo y, por lo tanto, la sendllamada escribirá los datos requeridos (40 bytes) en el búfer y regresará sin dar ningún error.

Cuando envía una porción más grande, la llamada de envío entra en estado de bloqueo.

La página del manual de envío también confirma esto:

Cuando el mensaje no cabe en el búfer de envío del socket, send () normalmente se bloquea, a menos que el socket se haya colocado en modo de E / S sin bloqueo. En modo sin bloqueo devolvería EAGAIN en este caso

Por lo tanto, mientras se bloquea el búfer libre disponible, si se notifica a la persona que llama (mediante el mecanismo de mantener vivo) que el otro extremo ya no está presente, la llamada de envío fallará.

Es difícil predecir el escenario exacto con la información mencionada, pero creo que esta debería ser la razón de su problema.

Vikram.exe
fuente
1
El estado actual del socket se observa mediante la actividad ACK. Keepalive es solo una actividad ACK de origen menor y está desactivada de forma predeterminada.
Marqués de Lorne
3

¿Quizás los 40 bytes quepan en el búfer de la tubería y los 40000 bytes no?

Editar:

El proceso de envío recibe una señal SIGPIPE cuando intenta escribir en una tubería cerrada. No sé exactamente cuándo se envía la señal o qué efecto tiene el búfer de tubería en esto. Es posible que pueda recuperarse capturando la señal con la llamada sigaction.

Joel
fuente
0

Cuando el par está cerca, simplemente no sabe si deja de enviar o si envía y recibe, ya que TCP permite esto, por cierto, debe conocer la diferencia entre cerrar y apagar. Si el par deja de enviar y recibir, primero envía algunos bytes, se realizará correctamente. Pero el kernel del mismo nivel le enviará RST. Entonces, posteriormente envía algunos bytes, su kernel le enviará la señal SIGPIPE, si capta o ignora esta señal, cuando su envío regresa, solo obtiene un error de tubería rota, o si no lo hace, el comportamiento predeterminado de su programa se bloquea .

Kingkong
fuente
-1

Tuvimos el error de tubería rota después de que se instaló una nueva red. Después de asegurarnos de que el puerto 9100 estaba abierto y podía conectarse a la impresora a través del puerto Telnet 9100, cambiamos el controlador de la impresora de "HP" a "PDF genérico", el error de tubería rota desapareció y pudimos imprimir correctamente.

(RHEL 7, las impresoras eran de la marca Ricoh, la configuración de HP era preexistente y funcional en la red anterior)

Andy T
fuente