Как я могу поймать SIGSEGV (ошибка сегментации) и получить трассировку стека под JNI на Android?

Я двигаюсьпроект в новый комплект разработки для Android (например, JNI), и я хотел бы поймать SIGSEGV, если это произойдет (возможно, также SIGILL, SIGABRT, SIGFPE), чтобы представить приятный диалог отчетности о сбоях вместо (или до) того, что в настоящее время случается: немедленная бесцеремонная смерть процесса и, возможно, попытка ОС перезапустить его. (Edit: JVM / Dalvik VM ловит сигнал и регистрирует трассировку стека и другую полезную информацию; Я просто хочу предложить пользователю возможность отправить эту информацию мне по-настоящему.)

Ситуация такова: большая часть кода на C, которую я не написал, выполняет большую часть работы в этом приложении (всю игровую логику), и, хотя она хорошо протестирована на многих других платформах, вполне возможно, что я в моем порте Android будет загружать мусор и вызывать сбой в нативном коде, поэтому я хочу, чтобы аварийные дампы (как нативные, так и Java) отображались в журнале Android (я думаю, это будет stderr в не Android) ситуация). Я свободен изменять код C и Java произвольно, хотя количество обратных вызовов (входящих и исходящих из JNI) составляет около 40, и, очевидно, бонусные баллы за небольшие различия.

Я слышал о библиотеке цепочки сигналов в J2SE, libjsig.so, и если бы я мог безопасно установить такой обработчик сигналов на Android, это решило бы важную часть моего вопроса, но я не вижу такой библиотеки для Android / Dalvik ,

Ответы на вопрос(4)

FWIW,Google Breakpad отлично работает на Android. Я выполнил работу по переносу, и мы отправляем ее как часть Firefox Mobile. Он требует небольшой настройки, поскольку он не дает вам трассировки стека на стороне клиента, но отправляет вам необработанную память стека и выполняет обработку стека на стороне сервера (поэтому вам не нужно отправлять символы отладки вместе с вашим приложением ).

По моему ограниченному опыту (не Android), SIGSEGV в коде JNI, как правило, приводит к сбою JVM, прежде чем управление возвращается в ваш код Java. Я смутно припоминаю, что слышал о какой-то не-Sun JVM, которая позволяет вам ловить SIGSEGV, но AFAICR вы не можете ожидать, что сможете это сделать.

Вы можете попытаться перехватить их в C (см. Sigaction (2)), хотя вы можете сделать очень мало после обработчика SIGSEGV (или SIGFPE или SIGILL), поскольку текущее поведение процесса официально не определено.

Я немного опоздал, но у меня была точно такая же необходимость, и я разработал небольшую библиотеку для решения этой проблемы, обнаруживая общие сбои (SEGV, SIBGUSи т. д.) внутриJNI codeи заменить их обычнымиjava.lang.Error exceptions, Бонус, если клиент работает на Android & gt; =4.1.1трассировка стека встраивает разрешенныйbacktrace сбоя (псевдо-трассировка, содержащая полную трассировку собственного стека). Вы не восстановитесь после злобных сбоев (например, если вы испортили распределитель, например), но, по крайней мере, это должно позволить вам восстановиться послеmost из них. (пожалуйста, сообщайте об успехах и неудачах, код совершенно новый)

Больше информации наhttps://github.com/xroche/coffeecatch (кодBSD 2-Clauses license)

Edit: От Jelly Bean и далее вы не можете получить трассировку стека, потому чтоREAD_LOGS went away. :-(

Я на самом деле получил обработчик сигнала, не делая ничего слишком экзотического, и выпустил код с его использованием, который вы можете увидетьна GitHub (редактировать: ссылка на историческую версию; с тех пор я удалил обработчик сбоя). Вот как:

Use sigaction() to catch the signals and store the old handlers. (android.c:570) Time passes, a segfault happens. In the signal handler, call up to JNI one last time and then call the old handler. (android.c:528) In that JNI call, log any useful debugging info, and call startActivity() on an activity that is flagged as needing to be in its own process. (SGTPuzzles.java:962, AndroidManifest.xml:28) When you come back from Java and call that old handler, the Android framework will connect to debuggerd to log a nice native trace for you, and then the process will die. (debugger.c, debuggerd.c) Meanwhile, your crash-handling activity is starting up. Really you should pass it the PID so it can wait for step 5 to complete; I don't do this. Here you apologise to the user and ask if you can send a log. If so, gather the output of logcat -d -v threadtime and launch an ACTION_SEND with recipient, subject and body filled in. The user will have to press Send. (CrashHandler.java, SGTPuzzles.java:462, strings.xml:41 Watch out for logcat failing or taking more than a few seconds. I have encountered one device, the T-Mobile Pulse / Huawei U8220, where logcat immediately goes into the T (traced) state and hangs. (CrashHandler.java:70, strings.xml:51)

В ситуации, не связанной с Android, некоторые из них будут другими. Вам нужно собрать свой собственный родной след, см.этот другой вопросв зависимости от того, какой у вас libc. Вам необходимо обработать дамп этой трассировки, запустить отдельный процесс обработчика сбоев и отправить электронное письмо некоторыми подходящими способами для вашей платформы, но я полагаю, что общий подход все еще должен работать.

ВАШ ОТВЕТ НА ВОПРОС