Je déplace un projet vers le nouveau kit de développement natif Android (c'est-à-dire JNI) et j'aimerais attraper SIGSEGV, si cela se produit (peut-être aussi SIGILL, SIGABRT, SIGFPE) afin de présenter une belle boîte de dialogue de rapport de plantage, au lieu de (ou avant) ce qui se passe actuellement: la mort immédiate et sans cérémonie du processus et éventuellement une tentative du système d'exploitation pour le redémarrer. ( Modifier: la machine virtuelle JVM / Dalvik capte le signal et enregistre une trace de pile et d'autres informations utiles; je veux juste offrir à l'utilisateur la possibilité de m'envoyer ces informations par courrier électronique.)
La situation est la suivante: un grand corps de code C que je n'ai pas écrit fait l'essentiel du travail dans cette application (toute la logique du jeu) et bien qu'il soit bien testé sur de nombreuses autres plates-formes, il est tout à fait possible que moi, dans mon Android port, va le nourrir des déchets et provoquer un crash dans le code natif, donc je veux les vidages sur incident (natifs et Java) qui apparaissent actuellement dans le journal Android (je suppose que ce serait stderr dans une situation non Android). Je suis libre de modifier arbitrairement le code C et Java, bien que les rappels (entrant et sortant de JNI) soient environ 40 et, évidemment, des points bonus pour les petits diffs.
J'ai entendu parler de la bibliothèque de chaînage de signaux dans J2SE, libjsig.so, et si je pouvais installer en toute sécurité un gestionnaire de signaux comme celui-ci sur Android, cela résoudrait la partie captivante de ma question, mais je ne vois aucune bibliothèque de ce type pour Android / Dalvik .
Réponses:
Edit: À partir de Jelly Bean, vous ne pouvez pas obtenir la trace de la pile, car il
READ_LOGS
est parti . :-(En fait, j'ai un gestionnaire de signaux fonctionnant sans rien faire de trop exotique, et j'ai publié du code en l'utilisant, que vous pouvez voir sur github (modifier: lien vers la version historique; j'ai supprimé le gestionnaire de crash depuis lors). Voici comment:
sigaction()
pour attraper les signaux et stocker les anciens gestionnaires. ( android.c: 570 )startActivity()
une activité signalée comme devant être dans son propre processus. ( SGTPuzzles.java:962 , AndroidManifest.xml: 28 )debuggerd
pour enregistrer une belle trace native pour vous, puis le processus mourra. ( debugger.c , debuggerd.c )logcat -d -v threadtime
et lancez unACTION_SEND
avec le destinataire, le sujet et le corps renseignés. L'utilisateur devra appuyer sur Envoyer. ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml: 41logcat
échecs ou aux prises de plus de quelques secondes. J'ai rencontré un appareil, le T-Mobile Pulse / Huawei U8220, où logcat passe immédiatement à l'étatT
(tracé) et se bloque. ( CrashHandler.java:70 , strings.xml: 51 )Dans une situation non Android, certains de ces éléments seraient différents. Vous auriez besoin de rassembler votre propre trace native, voir cette autre question , selon le type de libc dont vous disposez. Vous auriez besoin de gérer le vidage de cette trace, le lancement de votre processus de gestion des incidents séparé et l'envoi de l'e-mail de manière appropriée pour votre plate-forme, mais j'imagine que l'approche générale devrait toujours fonctionner.
la source
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
debuggerd
sorties?Je suis un peu en retard, mais j'avais le même besoin exact, et je l' ai développé une petite bibliothèque pour y remédier, en attrapant des accidents communs (
SEGV
,SIBGUS
, etc.) à l' intérieur du code JNI , et les remplacer par régulièresjava.lang.Error
exceptions . Bonus, si le client s'exécute sur Android> =4.1.1
, la trace de pile intègre la trace arrière résolue du crash (une pseudo-trace contenant la trace de pile native complète). Vous ne récupérerez pas de plantages vicieux (c'est-à-dire si vous corrompez l'allocateur, par exemple), mais au moins cela devrait vous permettre de récupérer de la plupart d'entre eux. (veuillez signaler les succès et les échecs, le code est tout neuf)Plus d'informations sur https://github.com/xroche/coffeecatch (le code est une licence BSD 2-Clauses )
la source
FWIW, Google Breakpad fonctionne très bien sur Android. J'ai fait le travail de portage et nous l'expédions dans le cadre de Firefox Mobile. Il nécessite un peu de configuration, car il ne vous donne pas de traces de pile côté client, mais vous envoie la mémoire brute de la pile et fait la marche de la pile côté serveur (vous n'avez donc pas à expédier de symboles de débogage avec votre application ).
la source
Dans mon expérience limitée (non-Android), SIGSEGV dans le code JNI plantera généralement la JVM avant que le contrôle ne soit retourné à votre code Java. Je me souviens vaguement avoir entendu parler d'une machine virtuelle Java non-Sun qui vous permet d'attraper SIGSEGV, mais AFAICR vous ne pouvez pas vous attendre à pouvoir le faire.
Vous pouvez essayer de les attraper en C (voir sigaction (2)), bien que vous puissiez faire très peu après un gestionnaire SIGSEGV (ou SIGFPE ou SIGILL) car le comportement en cours d'un processus est officiellement indéfini.
la source
_Unwind_Backtrace
deunwind.h
sera nécessaire à la place.