Comment puis-je attraper SIGSEGV (erreur de segmentation) et d'obtenir une trace de la pile en vertu de la JNI sur Android?
Je me déplace un projet vers la nouvelle Android Native Development Kit (c'est à dire JNI) et j'aimerais attraper SIGSEGV, si elle se produit (éventuellement aussi SIGILL, SIGABRT, SIGFPE) afin de présenter un beau crash de rapports de boîte de dialogue, au lieu de (ou avant) ce qui se passe: dans l'immédiat, unceremonious la mort du processus et éventuellement un peu de tenter par l'OS pour le redémarrer. (Edit: La JVM/Dalvik VM capte le signal et enregistre une trace de la pile et d'autres informations utiles; je veux juste offrir à l'utilisateur la possibilité d'envoyer un courriel à info pour moi, vraiment.)
La situation est la suivante: un grand corps d'un code C qui je n'ai pas écrit la plupart des travaux dans cette application (toute la logique du jeu) et bien c'est bien testé sur de nombreuses autres plateformes, il est tout à fait possible que j'ai, dans mon Android port, va nourrir d'ordures et de provoquer un plantage en code natif, donc je veux le crash dumps (à la fois indigène et Java) qui, actuellement, se montrer dans l'Android journal (je suppose que ce serait stderr dans un non-Android situation). Je suis libre de modifier à la fois le C et le Java code arbitraire, bien que les rappels (à la fois entrant et sortant de la JNI) nombre d'environ 40, et bien évidemment, les points de bonus pour les petites diff.
J'ai entendu le signal de chaînage de la bibliothèque dans J2SE, libjsig.donc, et si je pouvais en toute sécurité installer un gestionnaire de signal comme ça sur Android, qui permettrait de résoudre la capture partie de ma question, mais je ne vois pas de bibliothèque pour Android/Dalvik.
- Si vous pouvez démarrer la machine virtuelle Java par le biais d'un script, vous pouvez vérifier si l'application a quitté de façon anormale, et de faire le rapport d'erreur. Qui vous permettra à proprement attraper toutes sortes d'anomalies des sorties, qu'elles soient SIGSEGV, SIGKILL ou quoi que ce soit. Cependant, je ne pense pas que ce soit possible avec les actions des applications Android, de sorte que l'affichage de cette comme un commentaire (conversion à partir de la réponse).
- Voir aussi: Can pas exécuter une Java Android programme avec Valgrind pour savoir comment démarrer une application Android avec une surcouche de script (commande adb shell).
- La réponse doit être mis à jour. Le code source fourni dans l'acceptation de réponse entraînera un comportement indéfini en raison d'appeler à la non async-signal-les fonctions de sécurité. Veuillez voir ici: stackoverflow.com/questions/34547199/...
Vous devez vous connecter pour publier un commentaire.
Edit: Partir de Jelly Bean, vous ne pouvez pas obtenir la trace de la pile, parce que
READ_LOGS
s'en alla. 🙁J'ai effectivement eu un gestionnaire de signal de travail sans rien faire, trop exotique, et ont publié le code de l'utiliser, dont vous pouvez voir sur github (edit: liens vers des historiques de la libération; j'ai enlevé le crash gestionnaire depuis). Voici comment:
sigaction()
pour attraper les signaux et stocker les vieux maîtres. (android.c:570)startActivity()
sur une activité qui est signalée comme devant être dans son propre processus. (SGTPuzzles.java:962, AndroidManifest.xml:28)debuggerd
connecter une belle natif de trace pour vous, et puis le processus de mourir. (débogueur.c, debuggerd.c)logcat -d -v threadtime
et de lancer unACTION_SEND
avec le destinataire, l'objet et le corps rempli. L'utilisateur devra appuyer sur Envoyer. (CrashHandler.java, SGTPuzzles.java:462, les chaînes de caractères.xml:41logcat
défaut ou de prendre plus de quelques secondes. J'ai rencontré un seul appareil, le T-Mobile Pulse /Huawei U8220, où logcat va immédiatement dans l'T
(tracé) de l'état et se bloque. (CrashHandler.java:70, les chaînes de caractères.xml:51)Dans un non-Android situation, certains ce serait différent. Vous aurez besoin de recueillir votre propre natif de trace, voir cette autre question, en fonction de ce genre de libc vous avez. Vous auriez besoin de gérer de dumping qui trace, au lancement de votre distinct crash-gestionnaire de processus, et l'envoi de l'email dans certains des moyens appropriés pour votre plate-forme, mais j'imagine que l'approche générale doivent encore travailler.
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
debuggerd
sorties?Je suis un peu en retard, mais j'ai eu exactement le même besoin, et j'ai développé une petite bibliothèque pour y remédier, en attrapant commun des accidents (
SEGV
,SIBGUS
, etc.) à l'intérieur de JNI code, et de les remplacer par la régularité de lajava.lang.Error
exceptions. Bonus, si le client est en cours d'exécution sur Android >=4.1.1
, la trace de la pile intègre l'résolu backtrace de l'accident (un pseudo-trace contenant la native trace de la pile). Vous ne serez pas récupérer de vicieux se bloque (c'est à dire. si vous corrompre l'allocateur, par exemple), mais au moins, il devrait vous permet de récupérer d' plus d'entre eux. (veuillez signaler les réussites et les échecs, le code est tout nouveau)Plus d'info à https://github.com/xroche/coffeecatch
(le code est BSD 2-les Clauses de la licence)
FWIW, Google Breakpad fonctionne très bien sur Android. J'ai fait le portage de travail, et nous sommes de l'expédition dans le cadre de Firefox Mobile. Il nécessite un peu de configuration, car il ne vous donne pas les traces de pile sur le côté client, mais vous envoie les cru de la pile de la mémoire et la pile de marche côté serveur (si vous n'avez pas à expédier les symboles de débogage de votre application).
Dans mon expérience limitée (non-Android), SIGSEGV dans JNI code général plantage de la machine, avant que la commande est retournée à votre code Java. J'ai vaguement souvenir d'avoir entendu parler de certaines non-JVM de Sun, qui vous permet de prendre des SIGSEGV, mais AFAICR vous ne pouvez pas vous attendre à être en mesure de le faire.
Vous pouvez essayer de les attraper en C (voir sigaction(2)), bien que vous pouvez le faire très peu après un SIGSEGV (ou SIGFPE ou SIGILL) gestionnaire comme le comportement en cours d'un processus est officiellement défini.
_Unwind_Backtrace
deunwind.h
sera nécessaire plutôt.