2010-03-10 13 views
10
#include<stdio.h> 
#include<signal.h> 

void handler(int signo) 
{ 
    printf("Into handler\n"); 
    while(1); 
} 
int main() 
{ 
    struct sigaction act; 
    act.sa_handler = handler; 
    act.sa_flags = 0; 
    sigemptyset(& act.sa_mask); 
    sigaction(SIGINT, &act, NULL); 
    while(1); 
    return 0; 
} 

Después de agarrar la KeyboardInterrupt una vez, cuando se presiona la tecla "Ctrl + C" de nuevo, se SIGINT no se manejan ... tengo la intención de que "Into manejador" se imprimirán cada vez que presione "Ctrl + C".La captura de señal dentro de su propio manejador

Quiero coger SIGINT dentro del "controlador de SIGINT()" en sí ..

Respuesta

10

Es necesario configurar SA_NODEFER en sa_mask a coger la misma señal que la persona que está manejando actualmente:

SA_NODEFER: No evitar que la señal que se recibe desde el interior de su propio manejador de señales. SA_NOMASK es un sinónimo obsoleto y no estándar para esta bandera.

+0

Obtuve lo que quería ... Gracias ... :) –

+0

Cuidado: ¡esto no garantiza que no perderá señales! Si su proceso recibe señales múltiples, no en tiempo real del mismo tipo, mientras no está en el intervalo de tiempo o en la llamada ininterrumpida del núcleo, entonces la segunda (y más) señales se perderán. – peterh

1

El "while (1)" en el controlador está impidiendo que la primera llamada de servicio de volver jamás. Quite eso y las interrupciones subsecuentes deberían causar que el manejador sea llamado nuevamente.

Una rutina de servicio de interrupción no debe evitar que vuelva la secuencia de llamada.

+0

Quiero capturar SIGINT dentro del "gestor de SIGINT()" en sí ... –

+1

Luego, vuelva a escribir su kernel de Unix. – kmarsh

6

Lo que está haciendo parece una muy mala idea, y podría ser mejor simplemente establecer una bandera desde el controlador y volver desde allí, y luego hacer la impresión desde la pantalla principal.

Debe configurar SA_NODEFER o volver a habilitar la señal dentro del manejador de señal, ya que de lo contrario la señal se bloquea o cambia a su comportamiento predeterminado justo antes de la llamada al controlador.

Llamar a printf desde un manejador de señal es un comportamiento indefinido. Puede bloquear tu programa. La lista de funciones que puede llamar con seguridad desde un manejador de señal es muy limitada. I need a list of Async-Signal-Safe Functions from glibc

+0

+1 en el "parece una muy mala idea". En general, mantener sus manejadores de señal lo más cortos y simples posible es el camino a seguir. –

+0

por eso escribí "sigemptyset (& act.sa_mask);" para que no se enmascare ninguna señal ... ¿Dónde estoy equivocado? –

+0

En realidad, quiero aprender "cómo atrapar una señal particular dentro de su propio manejador de señales".Es por eso que hice la pregunta –

3

Uso de la función printf dentro de un manejador de la señal no es exactamente una buena idea de usar ya que puede provocar un comportamiento que no está definida! Al ejemplo de código le falta un bit vital para que el manejador de señal funcione ... Eche un vistazo a mi blog sobre este here en 'Q6. Cómo atrapar un error de segmentación? '

Además, debe reemplazar el bucle while con algo más sólido como una forma de salir del programa mientras prueba el manejador de señal ... como ... ¿cómo lo abandona?

+0

Acabo de empezar a leer sobre señales ... Entonces, ¿cuál es la forma correcta? –

+0

Mire el código, 'sigemptyset', luego se colocan los indicadores, y 'sigaction (SIGINT, & sigact, (struct sigaction *) NULL);' se llama después de ... que atrapa el SIGINT..esta configurando las banderas antes de llamar a 'sigemptyset' ... btw esto se usó en el entorno de producción y funciona felizmente en AIX ... – t0mm13b

2

se puede usar algo como esto en lugar de printf:

const char *str = "Into handler\n"; 
write(1, str, strlen(str)); 

La función write(..) es seguro para ser llamado desde hanlder señal. No olvide incluir el encabezado unistd.h para usarlo.

+1

Probablemente esté más seguro al referirse a 'stdout 'en lugar de' 1' como una variedad de medios podría causar que este número cambie. – RastaJedi

Cuestiones relacionadas