pthread_create - pthread_kill example c
POSIX hilos y seƱales (4)
- ¿Cuál es la mejor manera de controlar a qué hilo se envía una señal?
Como @zoli2k indicó, nombrar explícitamente un solo hilo para manejar todas las señales que desea manejar (o un conjunto de hilos con responsabilidades de señal específicas), es una buena técnica.
- ¿Cuál es la mejor manera de decirle a otro hilo (que en realidad podría estar ocupado) que la señal ha llegado? [...]
- ¿Cómo puedo manejar con seguridad pasando la información de que una señal ha ocurrido a otros hilos? ¿Esto tiene que suceder en el controlador de señal?
No diré "lo mejor", pero esta es mi recomendación:
Bloquee todas las señales deseadas en main
, de modo que todos los hilos hereden esa máscara de señal. Luego, configure el hilo de recepción de señal especial como un bucle de evento controlado por señal, despachando las señales recién llegadas como alguna otra comunicación dentro del hilo .
La forma más sencilla de hacerlo es hacer que el hilo acepte señales en un bucle utilizando sigwaitinfo
o sigtimedwait
. El hilo luego convierte las señales de alguna manera, tal vez transmitiendo un pthread_cond_t
, despertando otros hilos con más E / S, encolando un comando en una cola segura para subprocesos específica de la aplicación, lo que sea.
Alternativamente, el hilo especial podría permitir que las señales se entreguen a un manejador de señal, desenmascarándose para la entrega solo cuando estén listas para manejar las señales. (Sin embargo, la entrega de señal a través de manipuladores tiende a ser más propensa a errores que la aceptación de señales a través de la familia sigwait
). En este caso, el manejador de señal del receptor realiza alguna acción simple y asíncrona: configurar sig_atomic_t
flags, llamar a sigaddset(&signals_i_have_seen_recently, latest_sig)
, write
() un byte a un self-pipe sin bloqueo, etc. Luego, de vuelta en su bucle principal enmascarado, el hilo comunica la recepción de la señal a otros hilos como se indicó anteriormente.
( ACTUALIZADO @caf correctamente señala que los enfoques sigwait
son superiores).
He estado tratando de comprender las complejidades de cómo los hilos POSIX y las señales POSIX interactúan. En particular, estoy interesado en:
- ¿Cuál es la mejor manera de controlar a qué hilo se envía una señal (suponiendo que no sea fatal en primer lugar)?
- ¿Cuál es la mejor manera de decirle a otro hilo (que en realidad podría estar ocupado) que la señal ha llegado? (Ya sé que es una mala idea usar variables de condición pthread desde un manejador de señal).
- ¿Cómo puedo manejar con seguridad pasando la información de que una señal ha ocurrido a otros hilos? ¿Esto tiene que suceder en el controlador de señal? (En general, no quiero matar a los otros hilos, necesito un enfoque mucho más sutil).
Para referencia sobre por qué quiero esto, estoy investigando cómo convertir el paquete TclX para admitir subprocesos, o para dividirlo y al menos hacer que algunas partes útiles admitan subprocesos. Las señales son una de esas partes que es de particular interés.
De acuerdo con el estándar POSIX todos los hilos deberían aparecer con el mismo PID en el sistema y usando pthread_sigmask()
puede definir la máscara de bloqueo de señal para cada hilo.
Dado que se permite definir solo un manejador de señal por PID, prefiero manejar todas las señales en un hilo y enviar pthread_cancel()
si es necesario cancelar un hilo en ejecución. Es la forma preferida contra pthread_kill()
ya que permite definir funciones de limpieza para los hilos.
En algunos sistemas más antiguos, debido a la falta de compatibilidad adecuada con el núcleo, los subprocesos en ejecución pueden tener un PID diferente del PID del subproceso principal. Consulte las preguntas frecuentes sobre el manejo de señales con linuxThreads en Linux 2.4 .
Donde estoy hasta ahora:
- Las señales vienen en diferentes clases principales, algunas de las cuales normalmente deberían matar el proceso de todos modos (SIGILL) y algunas de las cuales nunca necesitan hacer nada (SIGIO, más fácil hacer asincrono IO correcto de todos modos). Esas dos clases no necesitan ninguna acción.
- Algunas señales no necesitan ser tratadas inmediatamente; los gustos de SIGWINCH pueden ponerse en cola hasta que sea conveniente (como un evento de X11).
- Los más complicados son aquellos en los que quieres responder al interrumpir lo que estás haciendo, pero sin llegar a eliminar un hilo. En particular, SIGINT en modo interactivo debería dejar las cosas sensibles.
Todavía tengo que ordenar a través de signal
vs sigaction
, pselect
, sigwait
, sigaltstack
y un montón de otros bits y piezas de API POSIX (y no POSIX).
En mi humilde opinión, las señales Unix V y posix no se mezclan bien. Unix V es 1970. POSIX es 1980;)
Hay puntos de cancelación y si permite las señales y los subprocesos en una sola aplicación, con el tiempo terminará escribiendo bucles alrededor de cada llamada, lo que sorprendentemente puede devolver EINTR.
Entonces, lo que hice en los (pocos) casos en que tuve que programar multiproceso en Linux o QNX fue, enmascarar todas las señales para todos (pero uno) hilos.
Cuando llega una señal V de Unix, el proceso cambia la pila (que era tanta concurrencia en Unix V como se podía obtener dentro de un proceso).
Como las otras publicaciones aquí insinúan, podría ser posible ahora, decirle al Sistema, qué hilo de posix será la víctima de esa conmutación de pila.
Una vez, lograste que tu hilo de manejo de señales funcione, la pregunta que queda es cómo transformar la información de la señal en algo civilizado, que otros hilos pueden usar. Se requiere una infraestructura para comunicaciones entre hilos. Un patrón, útil es el patrón de actor, donde cada uno de sus subprocesos es un objetivo para algún mecanismo de mensajería en proceso.
Entonces, en lugar de cancelar otros hilos o matarlos (u otras cosas extrañas), deberías tratar de utilizar la Señal del contexto de la Señal a tu hilo del Manejador de Señales, luego usar los mecanismos de comunicación de tu patrón de actores para enviar mensajes semánticamente útiles a esos actores. que necesitan la información relacionada con la señal.