Aparte del problema de "demasiadas señales", las señales pueden ignorarse explícitamente. De man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Las señales también se pueden bloquear. De man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
Los conjuntos secundarios de señales bloqueadas e ignoradas son heredadas por los procesos secundarios, por lo que puede ocurrir que el proceso principal de su aplicación ignore o bloquee una de estas señales.
¿Qué sucede cuando se entregan varias señales antes de que el proceso haya terminado de manejar las anteriores? Eso depende del sistema operativo. La página de signal(2)
manual vinculada anteriormente lo discute:
- El sistema V restablecería la disposición de la señal a la predeterminada. Peor aún, la entrega rápida de múltiples señales daría lugar a llamadas recursivas (?).
- BSD bloquearía automáticamente la señal hasta que el controlador esté listo.
- En Linux, esto depende de los indicadores de compilación establecidos para GNU
libc
, pero esperaría el comportamiento BSD.
signal(2)
sugiere enfáticamente que evite esta confusión al usar en susigaction(2)
lugar.No puede confiar en que se entregarán todas las señales enviadas. Por ejemplo, el kernel de Linux "fusiona" SIGCHLD si un proceso tarda mucho en manejar SIGCHLD desde un proceso hijo salido.
Para responder otra parte de su pregunta, las señales se "ponen en cola" dentro del núcleo si llegan varias señales diferentes en un intervalo demasiado corto.
Debe usar
sigaction()
para configurar el controlador de señal con elsa_sigaction
miembro desiginfo_t
, estableciendo elsa_mask
miembro delsiginfo_t
argumento con cuidado. Creo que esto significa enmascarar todas las señales "asíncronas" al menos. Según la página del manual para Linuxsigaction()
, también ocultará la señal que se está manejando. Creo que debería establecer elsa_flags
miembro en SA_SIGINFO, pero no recuerdo por qué tengo esta superstición. Creo que esto le dará a su proceso un controlador de señal que se mantiene sin condiciones de carrera, y que no se ve interrumpido por la mayoría de las otras señales.Escriba su función de controlador de señal con mucho, mucho cuidado. Básicamente, establezca una variable global para indicar que se atrapó una señal y haga que el resto del proceso se ocupe de la acción deseada para esa señal. Las señales se enmascararán por la menor cantidad de tiempo de esa manera.
Además, querrá probar su código de manejo de señal muy a fondo. Póngalo en un pequeño proceso de prueba y envíe tantas señales SIGUSR1 y SIGUSR2 como sea posible, tal vez desde 2 o 3 programas de envío de señales de propósito especial. Mezcle también algunas otras señales, después de que esté seguro de que su código puede manejar SIGUSR1 y SIGUSR2 de manera rápida y correcta. Prepárese para la depuración difícil.
Si usa Linux y solo Linux, puede pensar en usarlo
signalfd()
para crear un descriptor de archivo que puedaselect()
o sondear para recibir esas señales. El usosignalfd()
podría facilitar la depuración.fuente
Se garantiza que se entregará una señal, en el sentido de que si un proceso llama con éxito
kill
, entonces el objetivo recibirá la señal. Esto es asíncrono: el remitente no tiene forma de saber cuándo se recibe o procesa la señal. Sin embargo, esto no garantiza que se entregue la señal. El objetivo podría morir antes de poder procesar la señal. Si el objetivo ignora la señal en el momento en que se entrega, la señal no tendrá efecto. Si el objetivo recibe varias instancias del mismo número de señal antes de poder procesarlas, las señales pueden (y generalmente se combinan): si envía la misma señal dos veces a un proceso, no puede saber si el proceso recibirá la señal una o dos veces. Las señales están diseñadas principalmente para matar un proceso o como una forma de hacer que un proceso preste atención, no están diseñadas para la comunicación como tal.Si necesita una entrega confiable, entonces necesita un mecanismo de comunicación diferente. Hay dos mecanismos principales de comunicación entre procesos: una tubería permite la comunicación unidireccional; un socket permite la comunicación bidireccional y múltiples conexiones al mismo servidor. Si necesita que el destino procese tantas notificaciones como lo envíe, envíe bytes a través de una tubería.
fuente
El núcleo es libre de fusionar señales estándar si se entrega más de una mientras está bloqueado. Las señales en tiempo real, por otro lado, no tienen desventajas similares.
Desde la página del manual de la señal (7) :
Intente usar una señal con un número en el rango SIGRTMIN a SIGRTMAX.
fuente
ulimit -i
muestra este valor como 63432 en Ubuntu 18.04.