2011-12-27 7 views
8

Tengo un servidor de subprocesos múltiples (que usa subprocesos POSIX), con un subproceso para cada conexión persistente. En uno de los hilos, el otro extremo de la conexión se cierra, lo que da como resultado la entrega de un SIGPIPE. ¿Hay un (preferiblemente portátil) para determinar qué hilo (y por qué conexión) sucedió así puedo hacer que mi manejador de señal haga el trabajo de limpieza de conexión/subproceso mismo o establezca un indicador para que el hilo principal y el de trabajo respectivamente vean eso? necesitan hacerlo más tarde?POSIX Hilos/Señales: ¿forma portátil de determinar a qué hilo se ha enviado una señal?

EDIT: me pregunto si podría utilizar quizá & errno, almacenarlo en una matriz global y asociarlo con el identificador del servidor para el hilo, y luego buscar & errno en el manejador de la señal. ¿Sería el errno específico del subproceso visible para el manejador de señal? ¿Entiendo cómo funciona el hilo errno incluso en el estadio?

+0

Si se entregó una señal a un hilo en particular, ese hilo manejará la señal. Eso es lo que significa entregar una señal a un hilo específico. No entiendo lo que hay que verificar? –

+0

Porque eso no me dice qué hilo específico era. –

+0

No entiendo, el hilo es el hilo que maneja la señal. ¿Qué información sobre el hilo actual necesita saber? –

Respuesta

12

No lo creo, no. Una mejor solución para servidores multiproceso es suprimir la señal SIGPIPE (llamando al signal(SIGPIPE, SIG_IGN) como parte de la rutina de inicio del programa) y luego hacer que el hilo trate el valor de error (-1/EPIPE) devuelto por send().

Las señales y el multihilo no se mezclan bien.

+0

Había considerado esa posibilidad; el problema es que no detectaré la desconexión hasta la próxima vez que necesite enviar datos a través de esa conexión, que posiblemente nunca sea. –

+1

Esto podría detectarse fácilmente seleccionando en ese fd por error solamente –

+1

Mmm, tiene razón. Estoy usando epoll, y me olvidé de EPOLLHUP. –

0

Mi enfoque sería tener el controlador de señal para SIGPIPE simplemente escribir su ID de hilo en una variable global y utilizar algún otro mecanismo para señalar esto al hilo, que debería manejarlo.

+0

Bueno, eso todavía plantea la misma pregunta fundamental de qué manera portátil, segura para señales, tengo que descubrir en qué hilo particular sucedió esto, ya que tengo que descubrir cuál es la identificación del hilo. –

+0

Esto es bastante fácil: p. plantee un evento a través de cualquier mecanismo de evento que admita su sistema (esto incluye enviar algo a un conducto) y escuche estos eventos (que incluye la selección en ese conducto), lea la variable global (bloqueada) si es necesario y trabaje en es –

+0

Creo que un problema con el enfoque de variable global es lo que sucede si se generan dos señales en sucesión rápida: la segunda señal podría sobrescribir el valor escrito por la primera señal antes de que se ejecute el primer controlador. Necesitarías una cola FIFO protegida con un candado al menos ... pero luego te topas con el segundo problema, que es que no puedes bloquear un mutex desde dentro de un manejador de señal. –

0

¿Qué pasa con el uso de una variable global (declarada local de subprocesos) para almacenar el id del subproceso, inicializarlo en la creación del subproceso y consultarlo en el manejador de señal del subproceso.

Para más detalles sobre este CCG consulte aquí: http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html o más generales aquí: http://en.wikipedia.org/wiki/Thread-local_storage

+0

Las funciones de almacenamiento locales de subprocesos no son seguras, como yo lo entiendo. –

+0

@Steely Dan: No me refería a datos específicos de subprocesos que usan funciones para acceder a ellos. Por favor, vea la referencia que acabo de agregar a mi publicación, para lo que me refería en su lugar. – alk

1

Es posible utilizar pthread_self con seguridad en un manejador de señales. Es async-signal-safe.

Esta respuesta es para la posteridad. No recomiendo este enfoque técnicamente. Las otras respuestas y comentarios, sugiriendo un enfoque diferente, sería mejor implementarlos.

En el momento en que se planteó esta pregunta, la seguridad de pthread_self no era necesariamente obvia. El POSIX: Corrigendum técnico 1 de 2008, de 2013 (dos años después de que se formuló esta pregunta), aclara que pthread_self es explícitamente seguro de señal asíncrona, como se indica en el Linux signal(7) man page.

Relacionado, mencionó en comentarios que no estaba seguro si el núcleo "envía [un SIGPIPE] a cualquier hilo que no lo tiene bloqueado". Esa es una buena preocupación: ¿es una señal dirigida al proceso o una señal dirigida por el hilo? - y, afortunadamente, fuera de lugar. Un SIGPIPE generado por kernel es una señal "generada sincrónicamente" en respuesta a alguna llamada de E/S, y se envía al hilo de llamada. Esto se aclaró explícitamente en el Corrigéndum 2 (2004) a POSIX: 2001 para decir que un SIGPIPE en respuesta a un write es "sent to the thread" (énfasis añadido).

Cuestiones relacionadas