2010-02-10 9 views
5

Tengo una aplicación que consta de dos procesos (llamémoslos A y B), conectados entre sí a través de sockets de dominio Unix. La mayoría de las veces funciona bien, pero algunos usuarios informan del siguiente comportamiento:¿Qué puede causar un error EPIPE espontáneo sin finalizar la llamada close() o bloquearse?

  1. A envía una solicitud a B. Esto funciona. A comienza a leer la respuesta de B.
  2. B envía una respuesta a A. La llamada write() correspondiente devuelve un error EPIPE, y como resultado B cierra() el socket. Sin embargo, A hizo no close() el socket, ni se bloqueó.
  3. La llamada a read() de A devuelve 0, indicando el fin del archivo. A piensa que B cerró prematuramente la conexión.

usuarios también han informado de variaciones de este comportamiento, por ejemplo:

  1. A envía una solicitud a B. Esto funciona parcialmente, pero antes de que toda la solicitud se envía escritura de A() llamada devuelve EPIPE, y como resultado A close() el socket. Sin embargo, B no cerró() el socket, ni se bloqueó.
  2. B lee una solicitud parcial y de repente obtiene un EOF.

El problema es que no puedo reproducir este comportamiento localmente. He probado OS X y Linux. Los usuarios están en una variedad de sistemas, principalmente OS X y Linux.

cosas que ya he probado y considerado:

  • doble cierre() (cerrar insectos() se llama dos veces en el mismo descriptor de archivo): Probablemente no como que daría lugar a errores EBADF, pero No los he visto.
  • Aumentando el límite máximo de descriptor de archivo. Un usuario informó que esto funcionó para él, el resto informó que no.

¿Qué otra cosa puede causar un comportamiento como este? Sé con certeza que ni A ni B cierran() el zócalo prematuramente, y sé con certeza que ninguno de ellos se ha bloqueado porque tanto A como B pudieron informar el error. Es como si el kernel de repente decidiera desconectar el enchufe del zócalo por alguna razón.

Respuesta

3

Tal vez usted podría intentar strace como se describe en (o su GUI cousin.): http://modperlbook.org/html/6-9-1-Detecting-Aborted-Connections.html

que asuma que su problema está relacionado con el descrito aquí: http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable

Lamentablemente estoy teniendo un similar problem pero no pude arreglarlo con los consejos dados. Sin embargo, quizás esa cosa SO_LINGER funcione para usted.

+0

Resultó que el descriptor de archivo del servidor se agregó con el indicador EPOLLET a la cola de epoll que parece estar equivocado. – user206268

+2

¡No es exactamente la respuesta que estaba buscando, pero la página TCP a la que se vinculó es muy informativa! Ahora está abajo por Archive.org todavía lo tiene: http://ia700609.us.archive.org/22/items/TheUltimateSo_lingerPageOrWhyIsMyTcpNotReliable/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable .html – Hongli

2
  • shutdown() pueden haber sido llamado en uno de los puntos finales socket.

  • Si cualquiera de los lados puede bifurcar y ejecutar un proceso hijo , asegúrese de que la bandera FD_CLOEXEC (close-on-exec) se establece en el descriptor de archivo toma si lo hizo no la intención de que sea heredado por el niño . De lo contrario, el proceso secundario podría (accidentalmente o no) ser manipulando su conexión de socket.

+0

Gracias, pero ninguna de las situaciones es aplicable a mi programa. – Hongli

0

También verificaría que no haya un furtivo firewall en el medio. Es posible que un nodo de reenvío intermedio en la ruta envíe un RST.La mejor manera de realizar un seguimiento de que por supuesto es the packet sniffer

+0

... en un socket de dominio UNIX? Ese es un protocolo solo local. – ephemient

+0

Oh ... disparar, lo extrañé totalmente. Gracias. –

Cuestiones relacionadas