2012-04-18 26 views
23

Tengo una aplicación que utilizo para detectar cualquier falla de segmentación o ctrl-c. Utilizando el siguiente código, puedo detectar el error de segmentación, pero el controlador se llama una y otra vez. ¿Cómo puedo detenerlos? Para su información, no quiero salir de mi aplicación. Solo puedo cuidar de liberar todos los búferes corruptos.Manejo de falla de segmentación

¿Es posible?

void SignalInit(void) 
{ 

struct sigaction sigIntHandler; 

sigIntHandler.sa_handler = mysighandler; 
sigemptyset(&sigIntHandler.sa_mask); 
sigIntHandler.sa_flags = 0; 
sigaction(SIGINT, &sigIntHandler, NULL); 
sigaction(SIGSEGV, &sigIntHandler, NULL); 

} 

y manejador va así.

void mysighandler() 
{ 
MyfreeBuffers(); /*related to my applciation*/ 
} 

Aquí para la señal de error de segmentación, manejador está siendo llamado varias veces y MyfreeBuffers tan obvios() me da errores para liberar la memoria ya liberada. Solo quiero liberar una vez pero aún no quiero salir de la aplicación.

Por favor ayuda.

Respuesta

28

La acción predeterminada para cosas como SIGSEGV es finalizar su proceso, pero como ha instalado un controlador para ello, llamará a su controlador anulando el comportamiento predeterminado. Pero el problema es que la instrucción de falla de segmentación puede volverse a intentar después de que finaliza su controlador y si no ha tomado medidas para reparar el primer fallo seg, la instrucción reintentada volverá a fallar y continuará y seguirá.

Así que en primer lugar la instrucción que dio lugar a SIGSEGV y tratar de solucionarlo (se puede llamar algo así como backtrace() en el controlador y ver por sí mismo lo que salió mal)

Además, el estándar POSIX dice que,

El comportamiento de un proceso es indefinido después de que vuelve normalmente a partir de una función de captura de señal para un [XSI] SIGBUS, SIGFPE, SIGILL, o señal SIGSEGV que no fue generado por kill(), [RTS] sigqueue(), o raise().

Por lo tanto, lo ideal es corregir su segfault en primer lugar. de Manejador de violación de segmento no está destinado a pasar por alto la condición de error subyacente

Así que la mejor sugerencia sería: no atrapa al SIGSEGV. Deja que se descargue el núcleo. Analiza el núcleo. ¡Repare la referencia de memoria no válida y listo!

0

Bueno, podría establecer una variable de estado y solo memoria libre si no está configurada. El manejador de señal se llamará cada vez, no puede controlar ese AFAIK.

9

Si los SIGSEGV se dispara de nuevo, la conclusión obvia es que la llamada a MyfreeBuffers(); tiene no solucionado el problema subyacente (y si esa función realmente única free() algunos memoria asignada, no estoy seguro de por qué se podría pensar que haría).

Aproximadamente, un SIGSEGV se dispara cuando se intenta acceder a una dirección de memoria inaccesible. Si no va a salir de la aplicación, necesita hacer accesible esa dirección de memoria o cambiar la ruta de ejecución con longjmp().

6

No intente continuar después de SIG_SEGV. Básicamente significa que el entorno de su aplicación está dañado de alguna manera. Podría ser que acaba de desreferenciar un puntero nulo, o podría ser que algún error haya causado que su programa dañe su pila o el montón o alguna variable de puntero, simplemente no lo sabe. El único cosa segura es terminar el programa.

Es perfectamente legítimo manejar el control-C. Muchas aplicaciones lo hacen, pero debes ser muy cuidadoso con lo que haces en tu controlador de señal. No puede llamar a ninguna función que no sea reentrante. Eso significa que si su MyFreeBuffers() llama a la función stdlib free(), probablemente esté atornillado. Si el usuario acierta control-C mientras el programa está en el medio de malloc() o free() y por lo tanto a mitad de manipular las estructuras de datos que utilizan para rastrear asignaciones de montón, es casi seguro que dañará el montón si llama al malloc() o free() en la señal entrenador de animales.

La única cosa segura que puede hacer en un controlador de señal es establecer una bandera para indicar que ha detectado la señal. Su aplicación puede sondear la bandera a intervalos para decidir si necesita realizar alguna acción.

0

Puedo ver en el caso de una recuperación de un SIG_SEGV, si el manejo de eventos en un bucle y uno de estos eventos causa una Infracción de segmentación, entonces solo desea omitir este evento, continuar procesando los eventos restantes. En mi opinión, SIG_SEGV es similar a NullPointerException en Java. Sí, el estado será inconsistente y desconocido después de cualquiera de estos, sin embargo, en algunos casos, le gustaría manejar la situación y continuar. Por ejemplo, en Algo trading, pausarías la ejecución de un pedido y permitirías que un operador tomara el control manualmente, sin colapsar todo el sistema y arruinando el resto de los pedidos.

8

No estoy de acuerdo con la afirmación "No capte el SIGSEGV".

Esa es una muy buena práctica para tratar con condiciones inesperadas. Y eso es mucho más limpio para hacer frente a los NULL punteros (como los dados por las fallas malloc) con un mecanismo de señal asociado al setjmp/longjmp, que para distribuir la gestión de condiciones de error a lo largo de su código.

Nota sin embargo, que si se utiliza '' sigaction '' en SEGV, no debe olvidarse que decir SA_NODEFER en sa_flags - o encontrar otra manera de lidiar con el hecho de SEGV activará el controlador de una sola vez.

#include <setjmp.h> 
#include <signal.h> 
#include <stdio.h> 
#include <string.h> 

static void do_segv() 
{ 
    int *segv; 

    segv = 0; /* malloc(a_huge_amount); */ 

    *segv = 1; 
} 

sigjmp_buf point; 

static void handler(int sig, siginfo_t *dont_care, void *dont_care_either) 
{ 
    longjmp(point, 1); 
} 

int main() 
{ 
    struct sigaction sa; 

    memset(&sa, 0, sizeof(sigaction)); 
    sigemptyset(&sa.sa_mask); 

    sa.sa_flags  = SA_NODEFER; 
    sa.sa_sigaction = handler; 

    sigaction(SIGSEGV, &sa, NULL); /* ignore whether it works or not */ 

    if (setjmp(point) == 0) 
    do_segv(); 

    else 
    fprintf(stderr, "rather unexpected error\n"); 

    return 0; 
} 
+0

Esta es una buena solución. No me gustó especialmente el "déjalo colapsar y luego analicé el volcado del núcleo". – dturvene

Cuestiones relacionadas