Historias
Slashboxes
Comentarios
 

Login Barrapunto

Login

[ Crear nueva cuenta ]

mig21 (7781)

mig21
  reversethis-{moc.liamg} {ta} {pb12gim}
https://twitter.com/yapw

Hola, soy Miguel. Algo que pueda ser relevante aquí... Uhmm... Me gusta escribir en mi bitácora de BP [barrapunto.com] y en su clon en blogspot: Yet Another Programming Weblog [blogspot.com]
Me gustaría que Barrapunto fuese un sitio con más discusiones técnicas y trato de hacer lo que está en mi mano. De todos modos, también me gusta leer flames ;)

No creo que te interese, pero en Lecturas aleatorias [blogspot.com] dejo registro de los libros que voy leyendo...

Esta es toda mi información de usuario :)

Down Kill Up Publicidad

Bitácora de mig21 (7781)

Miércoles, 13 de Febrero 2008

Notas sobre errores fatales y portabilidad

09:47h.
Programación
Es escasa y dispersa la información que he encontrado acerca de la gestión de errores fatales en distintos sistemas operativos y lo que afecta al funcionamiento de los programas sobre ellos. Así que voy a juntar lo que he ido recopilando en una sola entrada. Puede ser un poco batiburrillo, pero igual le es de utilidad a alguien... (Para mi seguro, que así no pierdo los enlaces). Ordenadas de general a específico[1]:

  • En ANSI C existe signal que permite cambiar la gestión este tipo eventos, entre los que se encuentran SIGSEGV, violación de segmento y SIGFPE, error aritmético. No obstante, por desgracia, su comportamiento en programas con más de un thread no está especificado. Además por si fuese poco ANSI tampoco especifica el handler por defecto, es decir, qué es lo que pasa si salta una señal de ese tipo.
  • De hecho, de los que he probado, en windows con la librería de C del VisualStudio al menos, las señales funcionan por thread y en linux es global por proceso...
  • En POSIX si que se define el comportamiento por defecto de las señales. En concreto SIGSEGV y SIGFPE abortan el proceso completo . Se pueden ver los comportamientos por defecto de las distintas señales en POSIX en la documentación de <signal.h> del OpenGroup. Además, POSIX(R) recomienda pasarse a sigaction (que sólo es POSIX(R), no ANSI).
  • Windows NT no genera señal de violación de segmento, pero se le puede instalar handler
  • En win32 un error fatal se gestiona como una excepción estructurada (SHE) que en C++ se mapea a un excepción normal[2]. Además, una excepción estructurada no capturada, por defecto, supone la muerte del thread en el que se produce, pero no del proceso global .
  • Existe una forma de sobrescribir este comportamiento por defecto y es SetUnhandledExceptionFilter. Recomiendan en Nynaeve[3] no hacer cosas demasiado complicadas en el manejador, como parece lógico.
  • En un artículo de DeveloperWorks comentan un modo de convertir señales en excepciones pero que es un hack completamente erróneo: C++ exception-handling tricks for Linux porque da a entender que se puede replicar el comportamiento por defecto de Windows. Sin embargo, como se puede leer en "Program Error Signals" de la documentación de la glibc :

    La acción por defecto de todas estas señales es terminar el proceso. Si se bloquean o ignoran estas señales o se establece un handler que retorna normalmente, tu programa cascará espantosamente en el momento en que suceda la señal a no ser que(*) haya sido generada a través de raise o kill en lugar de un error real.
    cosa que he podido comprobar con el código de DW tratando de ignorar una violación de segmento.
  • En resumen, lo más juicioso (y homogéneo entre plataformas) sería parar el proceso completo en caso de uno de estos errores y tratar de informar lo más completamente posible del error. En caso de win32 habría que forzar el fin del proceso, ya que no es la acción por defecto[4].

[1]El orden es de mayor a menor, de general a específico. Debería ser obvio para un programador: a igualdad de condiciones, se debería usar lo que funcione en el estándar más aceptado y amplio ¿por qué limitar el ámbito de aplicación? Primero, buscar en ANSI, y si la funcionalidad no está elegir conscientemente una solución más específica. En el fondo para mi no es más que una consecuencia de la ley de Postel sobre el el código: "Cuanto más estricto (más estándar) es lo que escribes, más aumentarás la interoperabilidad". Puede parecer una obviedad, pero en esas pequeñas microdecisiones de los programadores no es nada extraño usar extensiones del estándar sin necesidad. Y en caso de necesidad se puede echar mano de librerías libres, muchas de ellas con un alto nivel de portabilidad.

[2]Pongo en cursiva normal porque entra la duda si en esos casos, de tan bajo nivel, una excepción, que se confunde con excepciones de de otro tipo, es lo más clarificador para el usuario-programador, máxime cuando el C++ estándar no posee excepciones para gestionar estos casos...

[3]Un blog que he descubierto hace poco... interesante. Además sobre el mismo tema: Beware of custom unhandled exception filters in DLLs y You might be using unhandled exception filters without even knowing it

[4]Cabe preguntarse porque se permite la ejecución del proceso en un caso tan excepcional... habida cuenta además de que una excepción no capturada de de C++ provoca, por defecto el fin del proceso... En este caso está sin duda justificado el Fail Fast : lo que hay que hacer es arreglar el programa, no dejarlo seguir...

(*) Me despisté al traducir. Gracias a Javier Noval por leerse los enlaces y hacerme notar el error ;)
Este hilo ha sido archivado. No pueden publicarse nuevos comentarios.
Mostrar opciones Umbral:
Y recuerda: Los comentarios que siguen pertenecen a las personas que los han enviado. No somos responsables de los mismos.