2009-07-04 5 views
81

새 Android Native Development Kit (예 : JNI)로 a project을 이동 중입니다. 멋진 충돌보고 대화 상자를 표시하기 위해 SIGSEGV를 잡으려고합니다 (SIGILL, SIGABRT, SIGFPE도 가능). 현재 일어나는 일 (또는 그 전에) : 즉각적인 예기치 않은 프로세스의 죽음과 OS가 다시 시도 할 수있는 시도. (편집 : JVM/Dalvik VM은 신호를 잡아서 스택 추적 및 기타 유용한 정보를 기록하므로 사용자에게 해당 정보를 나에게 이메일로 보낼 수있는 옵션을 제공하고 싶습니다.)안드로이드에서 JNI로 SIGSEGV (segmentation fault)를 잡아서 스택 트레이스를 얻으려면 어떻게해야합니까?

상황은 다음과 같습니다. a 필자가 작성하지 않은 C 코드의 많은 부분이이 애플리케이션 (모든 게임 로직)에서 대부분의 작업을 수행하며 수많은 다른 플랫폼에서 잘 테스트되었지만 안드로이드 포트에서 나는 그것을 먹을 가능성이 전적으로있다 쓰레기가 생겨서 원시 코드에서 충돌이 발생하므로 Android 로그에 현재 표시되는 크래시 덤프 (기본 및 Java 모두)를 원합니다 (Android 이외의 상황에서는 표준 오류 일 것으로 추측합니다). 콜백 (JNI로 들어가고 나오는 것 모두)은 약 40이고 분명히 작은 diffs에 대해서는 보너스 포인트이지만 C와 Java 코드를 임의로 수정할 수 있습니다.

J2SE, libjsig.so에서 신호 체인 라이브러리에 대해 들어 봤습니다. 안드로이드에서 신호 처리기를 안전하게 설치할 수 있다면 잡는 부분을 해결할 수 있지만 그 라이브러리는 없습니다. Android/Dalvik 용.

+0

당신이 래퍼 스크립트를 통해 자바 VM을 시작할 수 있다면, 당신이 할 수있는 (코드 BSD 2 절 라이센스입니다) 앱이 비정상적으로 종료되었는지 확인하고 오류보고를 수행합니다. 그렇게하면 SIGSEGV, SIGKILL 등 무엇이든간에 비정상 종료의 모든 종류를 깨끗하게 잡을 수 있습니다. 그러나, 나는 재고 애플 리케이션이 가능하다고 생각하지 않습니다, 그래서 코멘트로 이것을 게시 (답변에서). – sleske

+0

참조 : [Valgrind로 Java Android 프로그램을 실행할 수 없음] (http://stackoverflow.com/questions/13531496/cant-run-a-java-android-program-with-valgrind/19235439#19235439) for (adb 셸에서) 래퍼 스크립트로 안드로이드 앱을 시작하는 법. – sleske

답변

77

편집 : 이므로 젤리 빈부터 스택 추적을 얻을 수 없습니다. :-(

나는 실제로 이국적인 것을하지 않고 일하는 신호 처리기를 가지고 있으며, 이것을 사용하여 코드를 발표했다.이 코드는 on github (편집 : 과거 릴리스에 연결, 그 이후로 크래시 핸들러를 제거했다.)을 볼 수있다. 방법 :.. 시간이 지남에 (android.c:570)

  • 는, 세그멘트 폴트가 발생하는 신호를 잡아 이전 핸들러를 저장하는

    1. 사용 sigaction() 신호 처리기에서
    2. , JNI 하나에 다음 마지막 시간을 호출 이전 처리기를 호출하십시오. ( android.c:528)
    3. 해당 JNI 호출에서 유용한 디버깅 정보를 기록하고 자체 프로세스에 있어야한다고 플래그 된 활동에 startActivity()을 호출하십시오. (SGTPuzzles.java:962, AndroidManifest.xml:28)
    4. 자바에서 돌아와 이전 핸들러를 호출하면 Android 프레임 워크가 debuggerd에 연결되어 멋진 네이티브 추적을 로그 한 다음 프로세스가 종료됩니다. (debugger.c, debuggerd.c)
    5. 한편 충돌 처리 작업이 시작됩니다. 정말로 5 단계가 완료 될 때까지 기다릴 수 있도록 PID를 전달해야합니다. 나는 이것을하지 않는다. 여기에서 사용자에게 사과하고 로그를 보낼 수 있는지 묻습니다. 그렇다면 logcat -d -v threadtime의 결과를 수집하고 수신자, 제목 및 본문이 채워진 ACTION_SEND을 시작하십시오. 사용자는 보내기를 눌러야합니다.(CrashHandler.java, SGTPuzzles.java:462, strings.xml:41
    6. 실패 또는 몇 초 이상을 복용 logcat에주의. 나는 하나 개의 장치를 발견 한 로그 캣 즉시 T (추적) 상태와 중단에 들어가는 T - 모바일 펄스/화웨이 U8220, . (CrashHandler.java:70, strings.xml:51)이 아닌 안드로이드 상황에서

    ,이 중 일부는 다른 것입니다. 당신은 당신의 자신의 기본 추적을 수집해야 것, this other question를 참조하십시오, 당신은 libc의 어떤 종류에 따라 달라집니다. 당신에게 추적을 덤프 처리하고, 별도의 충돌 처리기 프로세스를 시작하고, 플랫폼에 맞는 적절한 방법으로 전자 메일을 보내야합니다. 그러나 나는 상상할 수 없습니다. 일반 접근 방식은 여전히 ​​작동해야합니다.

  • +2

    이상하게도 라이브러리에서 충돌이 발생했는지 확인하는 것이 좋습니다. 다른 곳에서 발생하면 (예 : VM 내부) JNI 신호 처리기의 호출은 상황을 오히려 혼란스럽게 할 수 있습니다. 어쨌든 중간 충돌이 발생하기 때문에 세상의 종말이 아니지만 VM 크래시 진단이 더 어려워 질 수 있습니다 (또는 기생하는 VM 크래시가 Android 버그 리포트 및 모든 사람들의 배플) – fadden

    +0

    이것에 대한 연구 프로젝트 공유를 위해 멋진 @Chris입니다! – olafure

    +0

    덕분에 JNI가 어디에서 열매를 맺고 있는지 발견하는 데 도움이되었습니다. – Nick

    5

    내 제한된 경험 (Android가 아닌)에서 JNI 코드의 SIGSEGV는 일반적으로 Java 코드로 제어가 반환되기 전에 JVM을 크래시합니다. 저는 당신이 SIGSEGV를 잡을 수있게 해주는 Sun JVM이 아닌 것에 대해 막연하게 회고했습니다. 그러나 AFAICR을 기대할 수는 없습니다.

    프로세스의 진행중인 동작이 공식적으로 정의되지 않았기 때문에 SIGSEGV (또는 SIGFPE 또는 SIGILL) 처리기를 거의 수행하지 않아도 C에서 처리하려고 할 수 있습니다 (sigaction (2) 참조).

    +0

    음, "ignor [ing] kill (2) 또는 raise (3)"에 의해 생성되지 않은 SIGFPE, SIGILL 또는 SIGSEGV 신호를 무시한 후 동작이 정의되지는 않지만 이러한 신호를 포착하는 동안 동작은 정의되지 않습니다. 현재 계획은 Java를 다시 호출하고 프로세스를 종료하지 않고 스레드를 종료하는 C 신호 처리기를 사용하는 것입니다. 이것은 가능하거나 불가능할 수 있습니다. :-) –

    +1

    C 백 트레이스 명령어 : http://stackoverflow.com/questions/76822/how-to-generate-a-stacktrace-when-my-c-app-crashes-using-gcc-compiler/77281#77281 –

    +1

    ... backtrace()를 사용할 수 없다는 점을 제외하고, 안드로이드는 glibc를 사용하지 않기 때문에 Bionic을 사용합니다. :-('unwind.h'의'_Unwind_Backtrace' 관련 작업이 필요할 것입니다 –

    6

    FWIW, Google Breakpad은 Android에서 잘 작동합니다. 필자는 포팅 작업을 수행했으며 파이어 폭스 모바일의 일부로 출하했습니다. 클라이언트 측에서 스택 추적을 제공하지는 않기 때문에 약간의 설정이 필요하지만 원시 스택 메모리를 보내고 서버 측에서 스택을 보냅니다 (따라서 디버그 심볼을 앱과 함께 제공 할 필요가 없습니다).). ,

    +1

    절대적으로 부족한 문서를 고려하여 Breakpad를 구성하는 것은 거의 불가능합니다. – shader

    +0

    정말 그렇게 어렵지는 않지만 프로젝트 위키에는 많은 설명서가 있습니다. 실제로 Android 용 NDK 빌드 Makefile이 있으므로 사용하기가 매우 편리해야합니다. http://code.google.com/p/google-breakpad/source/browse/trunk/README.ANDROID –

    +0

    안드로이드 용 디버그 심볼 파일을 전처리하는 모듈을 컴파일하면 리눅스에서만 컴파일 할 수있다. Mac에서 컴파일하면 Mac/iOS dSym 전 처리기 만 빌드됩니다. – shader

    14

    내가 늦게 조금 해요,하지만 난 똑같은 필요가 있고, 나는 JNI 코드 내부 (등 SEGV, SIBGUS) 일반적인 충돌을 잡기로,이를 해결하기위한 작은 도서관을 개발했습니다 일반 java.lang.Error예외로 교체하십시오 (). 보너스로, 클라이언트가 Android> = 4.1.1에서 실행중인 경우 스택 추적은 해결 된 백 트레이스 (전체 원시 스택 추적을 포함하는 유사 추적)을 내장합니다. 악의적 인 크래시 (예 : 할당자를 손상시킨 경우)에서 복구하지는 않지만 적어도 개에서 개까지 복구 할 수 있어야합니다. https://github.com/xroche/coffeecatch 에서

    더 많은 정보 (성공과 실패를보고하십시오, 코드가 새로운 브랜드가)

    관련 문제