Estou movendo um projeto para o novo Android Native Development Kit (ou seja, JNI) e gostaria de capturar o SIGSEGV, caso ocorra (possivelmente também SIGILL, SIGABRT, SIGFPE) para apresentar um bom diálogo de relatório de falha, em vez de (ou antes) o que acontece atualmente: a morte sem cerimônia imediata do processo e possivelmente alguma tentativa do SO de reiniciá-lo. ( Editar: O JVM / Dalvik VM capta o sinal e registra um rastreamento de pilha e outras informações úteis; eu só quero oferecer ao usuário a opção de enviar essas informações para mim, na verdade.)
A situação é: um grande corpo de código C que eu não escrevi faz a maior parte do trabalho neste aplicativo (toda a lógica do jogo) e embora seja bem testado em várias outras plataformas, é inteiramente possível que eu, no meu Android porta, irá alimentá-lo com lixo e causar uma falha no código nativo, então eu quero os despejos de memória (nativos e Java) que atualmente aparecem no log do Android (acho que seria stderr em uma situação não-Android). Estou livre para modificar o código C e Java arbitrariamente, embora os retornos de chamada (tanto entrando como saindo de JNI) totalizem cerca de 40 e, obviamente, pontos de bônus para pequenos diffs.
Já ouvi falar da biblioteca de encadeamento de sinal em J2SE, libjsig.so, e se eu pudesse instalar com segurança um manipulador de sinal como esse no Android, isso resolveria a parte contundente da minha dúvida, mas não vejo essa biblioteca para Android / Dalvik .
Respostas:
Edit: De Jelly Bean em diante, você não pode obter o rastreamento de pilha, porque
READ_LOGS
foi embora . :-(Na verdade, consegui um manipulador de sinais funcionando sem fazer nada muito exótico e lancei código usando-o, que você pode ver no github (editar: vinculando ao lançamento histórico; removi o manipulador de falhas desde então). Veja como:
sigaction()
para capturar os sinais e armazenar os manipuladores antigos. ( android.c: 570 )startActivity()
uma atividade que esteja sinalizada como necessitando estar em seu próprio processo. ( SGTPuzzles.java:962 , AndroidManifest.xml: 28 )debuggerd
para registrar um bom rastreio nativo para você, e então o processo morre. ( debugger.c , debuggerd.c )logcat -d -v threadtime
e execute umACTION_SEND
com destinatário, assunto e corpo preenchidos. O usuário terá que pressionar Enviar. ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml: 41logcat
falhas ou demore mais do que alguns segundos. Encontrei um dispositivo, o T-Mobile Pulse / Huawei U8220, onde o logcat imediatamente entra no estadoT
(rastreado) e trava. ( CrashHandler.java:70 , strings.xml: 51 )Em uma situação diferente do Android, algumas coisas seriam diferentes. Você precisaria coletar seu próprio rastreamento nativo, consulte esta outra pergunta , dependendo de que tipo de libc você tem. Você precisaria lidar com o despejo desse rastreio, iniciando seu processo separado de tratamento de falhas e enviando o e-mail de algumas maneiras apropriadas para sua plataforma, mas imagino que a abordagem geral ainda funcione.
fonte
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
debuggerd
saídas de qualquer coisa ?Eu sou um pouco tarde, mas eu tinha exatamente a mesma necessidade, e eu desenvolvi uma pequena biblioteca para enfrentá-lo, pela captura acidentes comuns (
SEGV
,SIBGUS
, etc.) dentro do código JNI , e substituí-los por regularesjava.lang.Error
exceções . Bônus, se o cliente estiver executando no Android> =4.1.1
, o rastreamento de pilha incorpora o rastreamento de volta resolvido da falha (um pseudo-rastreamento contendo o rastreamento de pilha nativo completo). Você não se recuperará de travamentos violentos (ou seja, se você corromper o alocador, por exemplo), mas pelo menos deve permitir que você se recupere da maioria deles. (por favor, relate sucessos e falhas, o código é novo)Mais informações em https://github.com/xroche/coffeecatch (o código é a licença BSD 2-Clauses )
fonte
FWIW, o Google Breakpad funciona bem no Android. Eu fiz o trabalho de portabilidade e estamos enviando como parte do Firefox Mobile. Requer um pouco de configuração, uma vez que não fornece rastreamentos de pilha no lado do cliente, mas envia a memória da pilha bruta e faz a pilha do lado do servidor (para que você não precise enviar símbolos de depuração com seu aplicativo )
fonte
Em minha experiência limitada (não Android), SIGSEGV no código JNI geralmente travará o JVM antes que o controle seja retornado ao seu código Java. Lembro-me vagamente de ouvir sobre alguma JVM não-Sun que permite capturar SIGSEGV, mas AFAICR você não pode esperar conseguir fazer isso.
Você pode tentar capturá-los em C (consulte sigaction (2)), embora você possa fazer muito pouco depois de um manipulador SIGSEGV (ou SIGFPE ou SIGILL), pois o comportamento contínuo de um processo é oficialmente indefinido.
fonte
_Unwind_Backtrace
deunwind.h
.