Domanda

mi sto muovendo un progetto al nuovo Android Native Development Kit (i.e.JNI) e mi piacerebbe catturare SIGSEGV, se dovesse verificarsi (possibilmente anche SIGILL, SIGABRT, SIGFPE) per presentare una bella finestra di dialogo di segnalazione degli arresti anomali, invece di (o prima) ciò che accade attualmente:l'immediata morte senza tante cerimonie del processo e forse qualche tentativo da parte del sistema operativo di riavviarlo.(Modificare: La VM JVM/Dalvik rileva il segnale e registra una traccia dello stack e altre informazioni utili;Voglio solo offrire all'utente la possibilità di inviarmi tali informazioni via email.)

La situazione è:una grande quantità di codice C che non ho scritto io svolge la maggior parte del lavoro in questa applicazione (tutta la logica del gioco) e sebbene sia ben testata su numerose altre piattaforme, è del tutto possibile che io, nel mio port Android, alimenterò è spazzatura e causa un arresto anomalo del codice nativo, quindi voglio i dump degli arresti anomali (sia nativi che Java) che attualmente vengono visualizzati nel registro Android (immagino che sarebbe stderr in una situazione non Android).Sono libero di modificare arbitrariamente sia il codice C che quello Java, sebbene i callback (sia in entrata che in uscita da JNI) siano circa 40 e ovviamente punti bonus per piccole differenze.

Ho sentito parlare della libreria di concatenamento del segnale in J2SE, libjsig.so, e se potessi installare in sicurezza un gestore di segnale come quello su Android, ciò risolverebbe la parte interessante della mia domanda, ma non vedo tale libreria per Android/Dalvik .

È stato utile?

Soluzione

Modificare: Da Jelly Bean in poi non puoi ottenere l'analisi dello stack, perché READ_LOGS andato via. :-(

In realtà ho fatto funzionare un gestore di segnale senza fare nulla di troppo esotico e ho rilasciato il codice che lo utilizza, come puoi vedere su github (modificare:collegamento alla versione storica;Da allora ho rimosso il gestore degli arresti anomali).Ecco come:

  1. Utilizzo sigaction() per catturare i segnali e memorizzare i vecchi gestori.(android.c:570)
  2. Il tempo passa, si verifica un segfault.
  3. Nel gestore del segnale, chiama JNI un'ultima volta e poi chiama il vecchio gestore.(android.c:528)
  4. In quella chiamata JNI, registra tutte le informazioni di debug utili e chiama startActivity() su un'attività contrassegnata come necessaria per essere inserita nel proprio processo.(SGTPuzzles.java:962, AndroidManifest.xml:28)
  5. Quando torni da Java e chiami il vecchio gestore, il framework Android si connetterà a debuggerd per registrare una bella traccia nativa per te, e quindi il processo morirà.(debugger.c, debuggerd.c)
  6. Nel frattempo, la tua attività di gestione degli incidenti sta iniziando.In realtà dovresti passargli il PID in modo che possa attendere il completamento del passaggio 5;Non lo faccio.Qui ti scusi con l'utente e chiedi se puoi inviare un log.Se è così, raccogli l'output di logcat -d -v threadtime e lancia un ACTION_SEND con destinatario, oggetto e corpo compilati.L'utente dovrà premere Invia.(CrashHandler.java, SGTPuzzles.java:462, stringhe.xml:41
  7. Attenzione logcat fallendo o impiegando più di qualche secondo.Ho riscontrato un dispositivo, il T-Mobile Pulse / Huawei U8220, in cui logcat entra immediatamente in T (tracciato) e si blocca.(CrashHandler.java:70, stringhe.xml:51)

In una situazione non Android, alcuni di questi sarebbero diversi.Dovresti raccogliere le tue tracce native, vedi quest'altra domanda, a seconda del tipo di libc che hai.Dovresti gestire il dump di quella traccia, avviare il processo separato di gestione degli arresti anomali e inviare l'e-mail in modi appropriati per la tua piattaforma, ma immagino che l'approccio generale dovrebbe comunque funzionare.

Altri suggerimenti

Sono un po' in ritardo, ma avevo esattamente la stessa esigenza e ho sviluppato una piccola libreria per risolverla, rilevando i crash più comuni (SEGV, SIBGUS, ecc.) all'interno Codice JNI, e sostituirli con normali java.lang.Error eccezioni.Bonus, se il client è in esecuzione su Android >= 4.1.1, l'analisi dello stack incorpora il file risolto retrocedere dell'arresto anomalo (una pseudo-traccia contenente l'intera traccia dello stack nativo).Non ti riprenderai da incidenti violenti (es.se corrompi l'allocatore, ad esempio), ma almeno dovrebbe consentirti il ​​ripristino maggior parte di loro.(si prega di segnalare successi e fallimenti, il codice è nuovo di zecca)

Maggiori informazioni su https://github.com/xroche/coffeecatch(il codice è Licenza BSD a 2 clausole)

FWIW, Blocco note di Google funziona bene su Android.Ho svolto il lavoro di porting e lo stiamo distribuendo come parte di Firefox Mobile.Richiede una piccola configurazione, poiché non fornisce tracce dello stack sul lato client, ma ti invia la memoria dello stack grezzo e esegue lo stack walk sul lato server (quindi non devi inviare simboli di debug con la tua app ).

Nella mia esperienza limitata (non Android), SIGSEGV nel codice JNI generalmente provoca l'arresto anomalo della JVM prima che il controllo venga restituito al codice Java.Ricordo vagamente di aver sentito parlare di alcune JVM non Sun che ti consentono di catturare SIGSEGV, ma AFAICR non puoi aspettarti di poterlo fare.

Puoi provare a catturarli in C (vedi sigaction(2)), anche se puoi fare molto poco dopo un gestore SIGSEGV (o SIGFPE o SIGILL) poiché il comportamento in corso di un processo è ufficialmente indefinito.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top