¿Cómo puedo detectar SIGSEGV (fallo de segmentación) y obtener un seguimiento de la pila en JNI en Android?

StackOverflow https://stackoverflow.com/questions/1083154

Pregunta

estoy moviéndome un proyecto al nuevo kit de desarrollo nativo de Android (es decir,JNI) y me gustaría capturar SIGSEGV, en caso de que ocurra (posiblemente también SIGILL, SIGABRT, SIGFPE) para presentar un agradable cuadro de diálogo de informe de fallas, en lugar de (o antes) lo que sucede actualmente:la muerte inmediata y sin ceremonias del proceso y posiblemente algún intento por parte del sistema operativo de reiniciarlo.(Editar: La JVM/Dalvik VM capta la señal y registra un seguimiento de la pila y otra información útil;Realmente solo quiero ofrecerle al usuario la opción de enviarme esa información por correo electrónico).

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 puerto de Android, alimente es basura y provoca un fallo en el código nativo, por lo que quiero los volcados de fallo (tanto nativos como Java) que aparecen actualmente en el registro de Android (supongo que sería estándar en una situación que no sea de Android).Soy libre de modificar el código C y Java de forma arbitraria, aunque las devoluciones de llamada (tanto las que entran como las que salen de JNI) suman alrededor de 40 y, obviamente, puntos de bonificación por pequeñas diferencias.

He oído hablar de la biblioteca de encadenamiento de señales en J2SE, libjsig.so, y si pudiera instalar de forma segura un controlador de señales como ese en Android, eso resolvería la parte difícil de mi pregunta, pero no veo dicha biblioteca para Android/Dalvik. .

¿Fue útil?

Solución

Editar A partir de la haba de jalea en adelante no se puede conseguir el seguimiento de pila, porque READ_LOGS se fueron . : - (

realidad tiene un manejador de señales de trabajo sin hacer nada demasiado exótico, y han lanzado código de usarlo, que se puede ver en github (edit: ligarse a la liberación histórica; quité el manejador de fallos desde entonces). He aquí cómo:

  1. Uso sigaction() para coger las señales y almacenar los viejos manipuladores. ( android.c: 570 )
  2. El tiempo pasa, una violación de segmento que ocurre.
  3. En el manejador de la señal, llamar hasta JNI una última vez y luego llamar al manejador de edad. ( android.c: 528 )
  4. En esa llamada JNI, registra ninguna información de depuración útil, y llamar startActivity() en una actividad que se marca como la necesidad de estar en su propio proceso. ( SGTPuzzles.java: 962 , AndroidManifest.xml: 28 )
  5. Cuando vuelvas de Java y llama a ese controlador antiguo, el marco Android se conectará a debuggerd para registrar un buen rastro nativa para usted, y entonces el proceso va a morir. ( debugger.c , debuggerd .c )
  6. Mientras tanto, la actividad de su accidente de manipulación se está iniciando. Realmente debe pasar el PID por lo que puede esperar a que el paso 5 para completar; No hago esto. Aquí te disculpas al usuario y pregunte si usted puede enviar un registro. Si es así, se reúnen la salida de logcat -d -v threadtime y lanzar un ACTION_SEND con destinatario, el asunto y el cuerpo rellenado. El usuario deberá pulsar el botón Enviar. ( CrashHandler.java , SGTPuzzles.java : 462 , strings.xml: 41
  7. Cuidado con los logcat fallar o tomar más de unos pocos segundos. He encontrado un dispositivo, el impulso T-Mobile / Huawei U8220, donde logcat inmediatamente entra en la T (rastreado) estado y se bloquea. ( CrashHandler.java: 70 , strings.xml: 51 )

En una situación de no-Android, algo de esto sería diferente. Que había necesidad de reunir a su propia traza nativo, consulte esta otra pregunta , dependiendo de qué tipo de libc que tiene. Que había necesidad de manejar el dumping que traza, el lanzamiento de su proceso de accidente-controlador separado, y enviar el correo electrónico de alguna manera apropiada para su plataforma, pero se imagina que el generalenfoque debería funcionar.

Otros consejos

Soy 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.) dentro de código JNI , y reemplazarlos por java.lang.Error regulares 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). Usted no va a recuperarse de anomalías vicioso (es decir. Si el asignador corrupta, por ejemplo), pero al menos lo que debería le permite recuperarse de más de ellos. (Por favor informe éxitos y fracasos, el código es completamente nuevo)

Más información en https://github.com/xroche/coffeecatch (Código es licencia BSD-2 cláusulas )

Fwiw, Google Breakpad funciona bien en Android. Hice el trabajo portar, y estamos enviarlo como parte de Firefox Mobile. Se requiere un poco de configuración, ya que no le da trazas de la pila en el lado del cliente, pero le envía la memoria de pila prima y hace la pila de caminar del lado del servidor (por lo que no tiene que enviar símbolos de depuración con su aplicación ).

En mi limitada experiencia (no androide), SIGSEGV en el código JNI general, se bloqueará la JVM antes se devuelve el control al código Java. Recuerdo vagamente oír hablar de algunos no JVM de Sun, que le permite ponerse SIGSEGV, pero AFAICR No se puede esperar a ser capaz de hacerlo.

Puede intentar atraparlos en C (ver sigaction (2)), aunque se puede hacer muy poco después de una violación de segmento (o SIGFPE o SIGILL) manipulador como el comportamiento en curso de un proceso es oficialmente definido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top