socket servidor programming program library how geeksforgeeks code cliente c++ c sockets client-server signals

c++ - programming - ¿Cómo prevenir SIGPIPE o evitar que el servidor finalice?



socket programming in c geeksforgeeks (3)

Un programa de servidor C ++ TCP bastante estándar que utiliza pthreads , bind , listen y accept . Tengo la situación de que el servidor finaliza (léase: se bloquea) cuando elimino un cliente conectado.

El motivo del bloqueo es que la llamada write() al archivo falla, por lo que el programa recibe un SIGPIPE. Y supongo que esto hace que el servidor salga.

Pensé, "por supuesto, la señal no controlada significa salida", así que usemos la signal() :

signal(SIGPIPE, SIG_IGN);

porque, tomado del man 2 write :

EPIPE fd está conectado a una tubería o toma cuyo extremo de lectura está cerrado. Cuando esto suceda, el proceso de escritura también recibirá una señal SIGPIPE. (Por lo tanto, el valor de retorno de escritura se ve solo si el programa captura, bloquea o ignora esta señal).

Por desgracia, no. Ni en el hilo del servidor ni en los hilos del cliente parece ayudar.

Entonces, ¿cómo evito que la llamada a write() eleve esa señal, o (para ser pragmático) cómo impido que el servidor salga?

Mis diagnósticos son:

  • hilo de servidor iniciado, vinculante, escuchar, aceptar.
  • dejar que un cliente se conecte (a través de telnet, por ejemplo)
  • enviar un pkill telnet para bloquear el cliente

comportamiento no deseado: el servidor sale, en gdb con

... in write () at ../sysdeps/unix/syscall-template.S:82 82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)

y la traza inversa :

#0 ... in write () at ../sysdeps/unix/syscall-template.S:82 #1 ... in ClientHandler::mesg(std::string) () #2 ... in ClientHandler::handle() () #3 ... in start_thread (arg=<value optimized out>) at pthread_create.c:300 #4 ... in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #5 ... in ?? ()


¿Por casualidad no hiciste la signal ignorar antes de engendrar hilos? Si esperó hasta más tarde, uno de los otros subprocesos podría recoger la señal y salir de su aplicación.

Si eso no funciona, siempre puede hacer un poll / select escritura antes de probar la escritura para asegurarse de que el socket sea grabable.


Cuando ignoras SIGPIPE, ya no obtienes una señal SIGPIPE, pero write() obtiene un error EPIPE .


Tarde en la fiesta, pero solo quería agregar algo para referencia futura: si está depurando su código en gdb, no olvide que anula sus manejadores de señal.

Por lo tanto, si ha configurado un manejador de señal como: signal (SIGPIPE, SIG_IGN) y parece que no funciona, intente ejecutar el código fuera del depurador.

O configure el handle SIGPIPE nostop (en el indicador gdb) para evitar que gdb se detenga en la señal.