2009-09-08 18 views
8

Tengo un programa que tiene que realizar ciertas tareas antes de que termine. El problema es que a veces el programa falla con una excepción (como no se puede acceder a la base de datos, etc.). Ahora, ¿hay alguna manera de detectar una terminación anormal y ejecutar algún código antes de que se muera?detectar la terminación del programa (C, Windows)

Gracias.

código es apreciado.

+0

utilizar un manejador SIGSEGV. ;-) –

Respuesta

9

1. Win32

La API de Win32 contiene una forma de hacerlo a través de la función SetUnhandledExceptionFilter, de la siguiente manera:

LONG myFunc(LPEXCEPTION_POINTERS p) 
{ 
    printf("Exception!!!\n");  
    return EXCEPTION_EXECUTE_HANDLER; 
} 

int main() 
{ 
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&myFunc);  
    // generate an exception ! 
    int x = 0; 
    int y = 1/x; 
    return 0; 
} 

2. POSIX/Linux

lo general Haga esto a través de la función signal() y luego maneje la señal SIGSEGV de manera apropiada. También puede manejar la señal SIGTERM y SIGINT, pero no SIGKILL (por diseño). Puede usar strace() para obtener una traza inversa para ver qué causó la señal.

+4

Además, con respecto a su comentario sobre TerminateProcess() ... la respuesta simple es que no puede hacer NADA después de que se invoca TerminateProcess() para su proceso. No apruebes, no cojas $ 200. Tu proceso sale, ahora. Período. El fin. – cigarman

+0

Gracias por los comentarios. El problema no son excepciones. El problema es detectar un bloqueo o una llamada de terminación. Excepciones que puedo manejar ya – wonderer

+0

Eso es lo que hace SetUnhandledExceptionFilter, maneja "bloqueos" como desbordamientos de pila, acceso a memoria nula, etc. No es solo un controlador de excepción en el sentido try/catch. – cigarman

1

Si es sólo para Windows, entonces usted puede utilizar SEH (SetUnhandledExceptionFilter), o VEH (AddVectoredExceptionHandler, pero es sólo para XP/2003 en adelante)

+0

Creo que esto podría ayudar. ¿tienes un fragmento de muestra? – wonderer

+0

http://codepad.org/mUAUB25D - pero esa es la más simple, hay manejadores de bloqueos más complejos en la red (por ejemplo, en CodeProject). –

+0

Lo intenté, se veía bien, pero si eliminé el proceso (del administrador de tareas, etc.) no lo detecta. – wonderer

2

Depende, ¿qué hacer con sus "excepciones". Si los maneja adecuadamente y sale del programa, puede registrar su función para llamar al salir, usando atexit().

No funcionará en caso de terminación anormal real, como segfault.

No sé nada de Windows, pero en el sistema operativo compatible con POSIX puede instalar un manejador de señal que captará diferentes señales y hará algo al respecto. Por supuesto, no puede atrapar SIGKILL y SIGSTOP.

Signal API es parte de ANSI C desde C89, por lo que probablemente Windows lo admita. Vea signal() syscall para más detalles.

+0

sí ... Necesito poder detectar una terminación normal y anormal ... – wonderer

+0

Estoy usando algo similar para captar ctrl-c y otras señales de terminación, pero no puedo detectar un Proceso de terminación. Si mal no puedo recordar un SIGKILL, lo mismo se aplica a TerminateProcess. Simplemente causa que la aplicación muera. – wonderer

0

En primer lugar, aunque esto es bastante obvio: Usted nunca puede tener una solución completamente robusta - alguien siempre puede golpear el cable de alimentación de interrumpir el proceso. Entonces, necesitas un compromiso, y debes diseñar cuidadosamente los detalles de ese compromiso.

Una de las soluciones más robustas es poner el código correspondiente en un programa contenedor. El programa envoltorio invoca su programa "real", espera a que finalice su proceso y luego, a menos que su programa "real" específicamente indique que se ha completado normalmente, ejecuta el código de limpieza. Esto es bastante común para cosas como los arneses de prueba, donde es probable que el programa de prueba se bloquee, aborte o muera de formas inesperadas.

Eso todavía le da la dificultad de lo que sucede si alguien hace un Proceso de terminación en su función de envoltura, si eso es algo de lo que debe preocuparse. Si es necesario, puede solucionarlo configurándolo como un servicio en Windows y utilizando las funciones del sistema operativo para reiniciarlo si se muere. (Esto simplemente cambia las cosas un poco, alguien podría simplemente detener el servicio). En este punto, probablemente se encuentre en un punto en el que necesite indicar la finalización exitosa mediante algo persistente como crear un archivo.

+0

Estoy de acuerdo contigo. Mi problema principal es realizar una última acción antes de morir en un Proceso de finalización u otro evento imprevisto. El resto de los eventos están cubiertos. Hablé con la persona a cargo del proyecto sobre la conversión de la aplicación de monitoreo a un servicio, pero eso es un no. Supongo que no hay forma de hacerlo ... – wonderer

5

Existen sysinternals forum threads sobre la protección contra intentos de procesos finales enganchando NT Internals, pero lo que realmente quieres es un proceso de vigilancia o de pares (enfoque razonable) o algún método para interceptar eventos catastróficos (bastante arriesgado).

Editar: Hay razones por las que hacen esto difícil, pero es posible interceptar o bloquear los intentos de matar a su proceso.Sé que estás tratando de limpiar antes de salir, pero tan pronto como alguien lanza un proceso que no puede ser eliminado de inmediato, alguien le pedirá un método para matarlo inmediatamente, y así sucesivamente. De todos modos, para ir por este camino, consulte el hilo enlazado anterior y busque algunas palabras clave que encuentre allí para obtener más información. gancho O filtro NtTerminateProcess etc. Estamos hablando de código kernel, controladores de dispositivo, antivirus, seguridad, malware, material de rootkit aquí. Algunos libros para ayudar en esta área son Windows NT/2000 Native API, Undocumented Windows 2000 Secrets: A Programmer's Cookbook, Rootkits: Subverting the Windows Kernel y, por supuesto, Windows® Internals: Fifth Edition. Estas cosas no son demasiado difíciles de codificar, pero son muy delicadas para hacer las cosas bien, y es posible que estés presentando efectos secundarios inesperados.

¿Quizás Application Recovery and Restart Functions podría ser útil? Compatible con Vista y Server 2008 y posteriores.

ApplicationRecoveryCallback de devolución de llamada Función función de devolución de llamada definido por la aplicación se utiliza para guardar los datos y la información de estado de aplicación en el caso de que la aplicación encuentra una excepción no controlada o no responde.

Sobre el uso de SetUnhandledExceptionFilter, MSDN Social discussion aconseja que para hacer este trabajo de forma fiable, remendar ese método en memoria es la única manera de estar seguro el filtro se llama. Aconseja envolver con __try/__ excepto. De todos modos, hay algunos ejemplos de código y discusión de filtrado de llamadas a SetUnhandledExceptionFilter en el artículo "SetUnhandledExceptionFilter" and VC8.

También, vea Windows SEH Revisited en The Awesome Factor para obtener un código de ejemplo de AddVectoredExceptionHandler.

+0

gracias. Vi esos antes. hay 2 problemas, aunque 1) Tengo que soportar XP. 2) No necesito recuperarme de un choque. Solo necesito guardar algunos archivos y cerrar las conexiones de db antes de cerrar la aplicación (ya sea con gracia o antes de colgar). – wonderer

+0

Gotcha. Se agregó información y enlaces al código de muestra y a la discusión de SUEF y AVEH. –

+0

déjame intentar esto. Aún así, no puedo atrapar un Proceso de terminación. Por lo que estoy viendo esto no es posible – wonderer

0

Publiqué un artículo en ddj.com sobre la "depuración post mortem" hace algunos años.

Incluye fuentes para Windows y Unix/Linux para detectar una terminación anómala. Por mi experiencia, sin embargo, un controlador de Windows instalado usando SetUnhandledExceptionFilter es no siempre llamado. En muchos casos se llama, pero recibo bastantes archivos de registro de clientes que no incluyen un informe de los controladores instalados, donde, por ejemplo, una causa de violación de ACCESO.

http://www.ddj.com/development-tools/185300443

+0

gracias. mi problema es que son excepciones calientes. – wonderer

Cuestiones relacionadas