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

голоса
82

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

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

Я слышал сигнала СЦЕПЛЕНИЕ библиотеки в J2SE, libjsig.so, и если бы я мог безопасно установить обработчик сигнала как то на Android, что позволит решить ловя часть моего вопроса, но я не вижу такой библиотеки для Android / Dalvik ,

Задан 05/07/2009 в 00:18
источник пользователем
На других языках...                            


4 ответов

голоса
77

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

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

  1. Используйте , sigaction()чтобы поймать сигналы и хранить старые обработчик. ( Android.c: 570 )
  2. Проходит время, выдаёт ошибку сегментации происходит.
  3. В обработчике сигнала вызова для JNI в последний раз , а затем вызвать старый обработчик. ( Android.c: 528 )
  4. В этом JNI вызов, бревенчатый любую полезную информацию для отладки, и вызвать startActivity()на деятельность , которая помечается как необходимости быть в своем собственном процессе. ( SGTPuzzles.java:962 , AndroidManifest.xml: 28 )
  5. Когда вы вернетесь из Java и называют этот старый обработчик, то Android рамки соединится debuggerdвойти хороший родной след для вас, и тогда процесс будет умирать. ( Debugger.c , debuggerd.c )
  6. В то же время, ваш краш-обработки активность запускается. На самом деле вы должны передать ему PID , поэтому он может ждать шага 5 завершения; Я не делаю этого. Здесь вы извинитесь перед пользователем и спросить , если вы можете отправить журнал. Если да, то соберите выход logcat -d -v threadtimeи запуск ACTION_SENDс получателем, темой и телом заполнено. Пользователь должен будет нажать Отправить. ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml: 41
  7. Следите за logcatнеудачу или принимать более чем на несколько секунд. Я сталкивался с одним устройством, Т-Mobile Pulse / Huawei U8220, где LogCat немедленно переходит в T(прослежена) состоянии и зависаний. ( CrashHandler.java:70 , strings.xml: 51 )

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

Ответил 24/11/2009 в 13:49
источник пользователем

голоса
14

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

Более подробная информация на https://github.com/xroche/coffeecatch (код BSD 2-Морозы лицензия )

Ответил 28/08/2013 в 18:08
источник пользователем

голоса
6

FWIW, Google Breakpad отлично работает на Android. Я сделал портирование работу, и мы грузить его как часть Firefox Mobile. Это требует немного установки, так как он не дает вам трассировку стеки на стороне клиента, но посылает вам необработанные памяти стеки и делает стек ходьбу на сторону сервера (так что вам не придется грузить отладочные символы с приложением ).

Ответил 08/11/2011 в 21:17
источник пользователем

голоса
5

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

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

Ответил 05/07/2009 в 02:55
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more