Estoy moviendo un proyecto al nuevo kit de desarrollo nativo de Android (es decir, JNI) y me gustaría detectar SIGSEGV, en caso de que ocurra (posiblemente también SIGILL, SIGABRT, SIGFPE) para presentar un cuadro de diálogo de informe de fallas agradable, en lugar de (o antes) de lo que sucede actualmente: la muerte inmediata y sin ceremonias del proceso y posiblemente algún intento del sistema operativo para reiniciarlo. ( Editar: JVM / Dalvik VM capta la señal y registra un seguimiento de pila y otra información útil; solo quiero ofrecer al usuario la opción de enviarme esa información por correo electrónico realmente).
La situación es: un gran cuerpo de código C que no escribí hace la mayor parte del trabajo en esta aplicación (toda la lógica del juego) y, aunque está bien probado en muchas otras plataformas, es muy posible que yo, en mi Android port, lo alimentará con basura y provocará un bloqueo en el código nativo, por lo que quiero los volcados de emergencia (tanto nativos como Java) que aparecen actualmente en el registro de Android (supongo que sería stderr en una situación que no sea de Android). Soy libre de modificar tanto el código C como el código Java arbitrariamente, aunque las devoluciones de llamada (tanto que entran como que salen de JNI) suman alrededor de 40 y obviamente, puntos de bonificación para diferencias pequeñas.
He oído hablar de la biblioteca de encadenamiento de señales en J2SE, libjsig.so, y si pudiera instalar de manera segura un controlador de señales como ese en Android, eso resolvería la parte de captura de mi pregunta, pero no veo tal biblioteca para Android / Dalvik .
Respuestas:
Editar: Desde Jelly Bean en adelante, no puede obtener el seguimiento de la pila, porque
READ_LOGS
desapareció . :-(De hecho, conseguí que un controlador de señales funcionara sin hacer nada demasiado exótico, y publiqué un código que lo usa, que puede ver en github (editar: vincular a la versión histórica; eliminé el controlador de fallos desde entonces). Así es cómo:
sigaction()
para captar las señales y almacenar los antiguos controladores. ( android.c: 570 )startActivity()
a una actividad que esté marcada como necesaria para estar en su propio proceso. ( SGTPuzzles.java:962 , AndroidManifest.xml: 28 )debuggerd
para registrar un buen seguimiento nativo para usted, y luego el proceso morirá. ( debugger.c , debuggerd.c )logcat -d -v threadtime
e inicie unACTION_SEND
destinatario, el asunto y el cuerpo completados. El usuario deberá presionar Enviar. ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml: 41logcat
fallar o tomar más de unos segundos. Encontré un dispositivo, el T-Mobile Pulse / Huawei U8220, donde logcat entra inmediatamente en el estadoT
(rastreado) y se cuelga. ( CrashHandler.java:70 , strings.xml: 51 )En una situación sin Android, algo de esto sería diferente. Debería recopilar su propio rastro nativo, ver esta otra pregunta , dependiendo del tipo de libc que tenga. Debería manejar el volcado de ese rastro, iniciar su proceso de manejo de fallas por separado y enviar el correo electrónico de alguna manera apropiada para su plataforma, pero imagino que el enfoque general aún debería funcionar.
fuente
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
debuggerd
salidas?Estoy un poco tarde, pero tenía exactamente la misma necesidad, y he desarrollado una pequeña biblioteca para hacer frente a ella, por la captura de los accidentes comunes (
SEGV
,SIBGUS
, etc.) en el interior de código JNI , y reemplazarlos por regularesjava.lang.Error
excepciones . Bonificación, si el cliente se ejecuta en Android> =4.1.1
, el seguimiento de pila incrusta el resuelta traza del accidente (un pseudo-trace que contiene la traza completa pila nativa). No se recuperará de fallas viciosas (es decir, si corrompe el asignador, por ejemplo), pero al menos debería permitirle recuperarse de la mayoría de ellas. (informe los éxitos y los fracasos, el código es nuevo)Más información en https://github.com/xroche/coffeecatch (el código es licencia BSD de 2 cláusulas )
fuente
FWIW, Google Breakpad funciona bien en Android. Hice el trabajo de portabilidad y lo enviaremos como parte de Firefox Mobile. Requiere una pequeña configuración, ya que no le da rastros de pila en el lado del cliente, pero le envía la memoria de pila sin procesar y hace que la pila recorra el lado del servidor (por lo que no tiene que enviar símbolos de depuración con su aplicación ).
fuente
En mi experiencia limitada (no Android), SIGSEGV en el código JNI generalmente bloqueará la JVM antes de que se devuelva el control a su código Java. Recuerdo vagamente haber escuchado acerca de una JVM que no es de Sun y que le permite capturar SIGSEGV, pero AFAICR no puede esperar poder hacerlo.
Puede intentar capturarlos en C (consulte sigaction (2)), aunque puede hacer muy poco después de un controlador SIGSEGV (o SIGFPE o SIGILL), ya que el comportamiento continuo de un proceso no está definido oficialmente.
fuente
_Unwind_Backtrace
deunwind.h
.