Pregunta

Estoy escribiendo un programa crítico para una distribución de Linux que estoy desarrollando. Necesita reiniciarse al recibir ciertas señales, para tratar de evitar fallas. El problema es que, después del reinicio, no puedo volver a habilitar esa señal. Es decir, la señal no se puede recibir dos veces. Después de ejecutarse (), cuando el nuevo proceso llama a la señal () para configurar la señal, se devuelve SIG_DFL. Cada vez. Incluso si lo llamo dos veces seguidas, lo que indica que nunca se configuró en primer lugar. ¿Se está transfiriendo alguna bandera extraña del proceso original?

¿Fue útil?

Solución

Te estás equivocando por el hecho de que esencialmente estás tratando de manejar recursivamente una señal.

Cuando se usa signal() para registrar un controlador de señal, ese número de señal se bloquea hasta que el controlador de señal regrese; en efecto, el núcleo / libc bloquea ese número de señal cuando se invoca el controlador de señal, y lo desbloquea después de que el controlador de señal regrese . Como nunca regresa del controlador de señal (en su lugar, execl un nuevo binario), SIGUSR1 permanece bloqueado y, por lo tanto, no se detecta la segunda vez.

Esto se puede ver examinando /proc/</pid>/status antes y después de enviar el primer SigCgt.

Antes:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000000
SigCgt: 0000000000000200

Después:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000200
SigCgt: 0000000000000200

Tenga en cuenta que man signal(7) indica que la señal 10 está registrada (el número es un campo de bits; el décimo bit está configurado, lo que equivale a SIGUSR1; consulte SigBlk para ver los números). SIGUSR está vacío antes de que se envíe sighandler a su proceso, pero después de enviar la señal contiene sigaction.

Tienes dos formas de resolver esto:

a). Desbloquee manualmente SA_NODEFER antes de llamar a signal en <=>:

sigset_t sigs;
sigprocmask(0, 0, &sigs);
sigdelset(&sigs, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigs);

b). Use <=> con la bandera <=> en lugar de <=> para registrar el controlador de señal. Esto evitará que <=> se bloquee dentro del controlador de señal:

struct sigaction act;
act.sa_handler = signalhandler;
act.sa_mask = 0;
act.sa_flags = SA_NODEFER;
sigaction(SIGUSR1, &act, 0);

Otros consejos

Los manejadores de señales no se heredan en exec porque SIG_IGN sobrescribe su espacio de direcciones completo, y cualquier manejador de señales que no se restablezca estaría apuntando al lugar equivocado. El único momento en que no se restablece es si está configurado en, por ejemplo, <=>, que no depende del espacio de direcciones del proceso pre - <=>.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top