2012-01-12 13 views
9

Tengo un controlador de señal registrado en mi programa. Al recibir una señal no deseada (SIGABRT), llamo 'exit (-1)' en el manejador de señal para salir del proceso. Pero como se notó en algunas ocasiones, llama a exit() pero falla al finalizar el proceso.¿Puede la salida() no finalizar el proceso?

El problema se generó de forma aleatoria y sospecho fuertemente de la ejecución de exit().

Puede haber razones o casos en los que la salida() puede no finalizar el proceso.

Gracias.

+1

Ciertamente le aconsejo que busque otra causa del error que una función como 'exit'.Casi siempre, cuando piensas que hay un error en el compilador o en la biblioteca estándar, etc., es tu propio error el que está causando el error. – Shahbaz

+3

@Shahbaz: Mandar no pregunta por un error en la implementación, o sugiere que exista. La pregunta es si 'exit' se especifica para terminar siempre el programa, y ​​la respuesta es no (y especialmente no si se llama desde un manejador de señal). –

+0

¿Por qué no simplemente configura el manejador de SIGABRT para salir()? Cualquier otra cosa que esté haciendo en el controlador de señal, hágalo en una llamada atexit(). –

Respuesta

13

¿Está llamando al exit() desde el controlador de señal?

En man 7 signal, sección asíncrono señal segura funciones se pueden ver todas las funciones que están garantizados para trabajar cuando se llama desde un manejador de señales:

una función de controlador de señal debe tener mucho cuidado, ya el procesamiento en otro lugar puede interrumpirse en algún punto arbitrario en la ejecución del programa. POSIX tiene el concepto de "función segura". Si una señal interrumpe la ejecución de una función insegura, y el controlador llama a una función insegura, entonces el comportamiento del programa no está definido.

POSIX.1-2004 (también conocido como POSIX.1-2001 Técnica Corrección de errores 2) requiere una implementación a garantía de que las siguientes funciones se pueden llamar de forma segura dentro de un manejador de señales:

Hay que pueda ver funciones _Exit(), _exit() y abort(), pero notablemente no exit(). Entonces no deberías llamarlo desde un manejador de señal.

Lo malo es que incluso si llama a una función insegura de un manejador de señal (printf() ¿alguna?) Simplemente funcionará la mayor parte del tiempo ... pero no siempre.

+1

Llamar a una función de señal asíncrona insegura desde un manejador de señal es * perfectamente legal * a menos que la señal haya interrumpido otra función de señal asíncrona insegura. Esto explica el motivo por el que funciona "la mayoría de las veces", pero también significa que puede usar funciones de señal asíncrona insegura en manejadores de señal incluso en código correcto y robusto si se asegura de que el manejador de señal no pueda interrumpir un estado inseguro función (por ejemplo, dejar la señal enmascarada la mayor parte del tiempo y solo desbloquearla mientras se realizan llamadas de biblioteca aritméticas puras o de señal asíncrona como el descriptor de archivo IO y 'select'). –

+0

@R .. Tienes razón, por supuesto. Pero en la práctica es difícil garantizar eso, excepto en casos muy particulares. Personalmente encuentro mucho más conveniente para evitar todas las funciones inseguras. – rodrigo

+1

Vea también: http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html –

3

Sí, hay algunas circunstancias, tales como:

La función exit() llamará primero todas las funciones registradas por atexit(), en el orden inverso al de su inscripción, salvo que una función se llama después de cualquier función previamente registrada que ya se había llamado en el momento en que se registró. Cada función se llama tantas veces como se registró. Si, durante la llamada a cualquiera de estas funciones, se realiza una llamada a la función longjmp() que terminaría la llamada a la función registrada, el comportamiento no está definido.

Si una función registrada por una llamada a atexit() no puede regresar, las funciones registradas restantes no serán llamadas y el resto del proceso de salida() no se completará. Si se llama a exit() más de una vez, el comportamiento no está definido.

Consulte la página POSIX en exit.

Para obtener más información, adjunte un depurador cuando llegue a la situación y eche un vistazo a la pila de llamadas.

Cuestiones relacionadas