- ¿Cuál es la mejor manera de controlar a qué hilo se envía una señal?
Como indicó @ zoli2k, nombrar explícitamente un solo hilo para manejar todas las señales que desea manejar (o un conjunto de hilos, cada uno 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 de manera segura la transmisión de información de que se ha producido una señal a otros hilos? ¿Es necesario que esto suceda en el manejador de señales?
No diré "mejor", pero esta es mi recomendación:
Bloquea todas las señales deseadas main
para que todos los hilos hereden esa máscara de señal. Luego, modele el subproceso de recepción de señales especiales como un bucle de eventos impulsado por señales, enviando las señales recién llegadas como alguna otra comunicación dentro del subproceso .
La forma más sencilla de hacer esto es hacer que el hilo acepte señales en un bucle usando sigwaitinfo
osigtimedwait
. Luego, el hilo convierte las señales de alguna manera, tal vez transmitiendo un pthread_cond_t
, despertando otros hilos con más E / S, colocando un comando en una cola segura para hilos específica de la aplicación, lo que sea.
Alternativamente, el hilo especial podría permitir que las señales se envíen a un manejador de señales, desenmascarando para su entrega solo cuando esté listo para manejar señales. ( sigwait
Sin embargo, la entrega de señales a través de manejadores tiende a ser más propensa a errores que la aceptación de señales a través de la familia). En este caso, el manejador de señales del receptor realiza una acción simple y segura para señales asíncronas: establecer sig_atomic_t
banderas, llamar sigaddset(&signals_i_have_seen_recently, latest_sig)
, write
() un byte a una de no bloqueo auto-tubo , etc. a continuación, de nuevo en su bucle principal enmascarado, el hilo se comunica la recepción de la señal a otros hilos como anteriormente.
( ACTUALIZADO @caf señala con razón que los sigwait
enfoques son superiores).
sigwaitinfo()
(osigtimedwait()
) y luego los envía al resto de la aplicación como se describe en el último párrafo.De acuerdo con el estándar POSIX, todos los subprocesos deben aparecer con el mismo PID en el sistema y, mediante el uso
pthread_sigmask()
, puede definir la máscara de bloqueo de señal para cada subproceso.Dado que se permite definir solo un controlador 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 en contrapthread_kill()
ya que permite definir funciones de limpieza para los subprocesos.En algunos sistemas más antiguos, debido a la falta de soporte del kernel adecuado, 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 .
fuente
make menuconfig
con la rama git master recién clonada de uClibc. No es una elección entre los viejos y los nuevos hilos de Linux NTPL como implementaciones de hilos POSIX, pero la ayuda a partir del año 2012 todavía no recomienda elegir NTPL. Por lo tanto, es común todavía en los sistemas Linux embebidos modernos ver la implementación obsoleta de LinuxThreads utilizada, incluso si el sistema está ejecutando un kernel de Linux suficientemente reciente.Dónde estoy hasta ahora:
Todavía tengo que ordenar a través
signal
vssigaction
,pselect
,sigwait
,sigaltstack
, y un montón de otras partes y piezas de POSIX (y no POSIX) de la API.fuente
En mi humilde opinión, las señales de Unix V y los subprocesos posix no se mezclan bien. Unix V es 1970. POSIX es 1980;)
Hay puntos de cancelación y si permite señales y pthreads en una aplicación, eventualmente terminará escribiendo Loops alrededor de cada llamada, lo que sorprendentemente puede devolver EINTR.
Entonces, lo que hice en los (pocos) casos en los que tuve que programar multiproceso en Linux o QNX fue enmascarar todas las señales para todos los subprocesos (excepto uno).
Cuando llega una señal Unix V, el proceso cambia la pila (esa era la mayor cantidad de simultaneidad en Unix V que se podía obtener dentro de un proceso).
Como sugieren las otras publicaciones aquí, podría ser posible ahora, decirle al Sistema, qué hilo posix será la víctima de ese cambio de pila.
Una vez que logró que su hilo de manejo de señales funcionara, la pregunta sigue siendo cómo transformar la información de la señal en algo civilizado que otros hilos pueden usar. Se requiere una infraestructura para las comunicaciones entre subprocesos. Un patrón, útil es el patrón de actor, donde cada uno de sus hilos es un objetivo para algún mecanismo de mensajería en proceso.
Entonces, en lugar de cancelar otros subprocesos o matarlos (u otras cosas raras), debe intentar ordenar la señal del contexto de la señal a su subproceso del controlador de la señal, luego use sus mecanismos de comunicación de patrón de actor para enviar mensajes semánticamente útiles a esos actores, que necesitan la información relacionada con la señal.
fuente