Android의 JNI에서 SIGSEGV (세분화 오류)를 포착하고 스택 추적을 얻으려면 어떻게해야합니까?
프로젝트 를 새로운 Android 네이티브 개발 키트 (예 : JNI) 로 옮기고 있는데 SIGSEGV가 발생하면 (아마도 SIGILL, SIGABRT, SIGFPE) 대신 멋진 충돌보고 대화 상자를 표시하기 위해 포착하고 싶습니다. (또는 그 이전에) 현재 일어나는 일 : 프로세스의 즉각적인 무의식적 인 죽음과 OS가 프로세스를 다시 시작하려는 시도. ( 편집 : JVM / Dalvik VM은 신호를 포착하고 스택 추적 및 기타 유용한 정보를 기록합니다. 사용자에게 해당 정보를 실제로 이메일로 보낼 수있는 옵션을 제공하고 싶습니다.)
상황은 다음과 같습니다. 제가 작성하지 않은 큰 C 코드는이 애플리케이션 (모든 게임 로직)에서 대부분의 작업을 수행하며 다른 수많은 플랫폼에서 잘 테스트되었지만 Android에서 전적으로 가능합니다. 포트는 가비지를 공급하고 네이티브 코드에서 크래시를 유발하므로 현재 Android 로그에 표시되는 크래시 덤프 (네이티브 및 Java 모두)를 원합니다 (Android가 아닌 상황에서는 stderr 일 것임). C와 Java 코드를 임의로 수정할 수 있지만, 콜백 (JNI에 들어오고 나가는 것 모두)이 약 40 개이고 분명히 작은 차이에 대한 보너스 포인트가 있습니다.
J2SE, libjsig.so의 신호 체인 라이브러리에 대해 들었고 Android에 이와 같은 신호 핸들러를 안전하게 설치할 수 있다면 내 질문의 포착 부분을 해결할 수 있지만 Android / Dalvik 용 라이브러리는 없습니다. .
편집 : 때문에 젤리 빈에서는 이후 당신은 스택 추적을 얻을 수 없다 READ_LOGS
멀리 갔다 . :-(
나는 실제로 너무 이국적인 것을하지 않고 작동하는 신호 처리기를 얻었고 그것을 사용하여 코드를 릴리스 했습니다 .github에서 볼 수 있습니다 (편집 : 기록 릴리스에 연결; 그 이후로 충돌 처리기를 제거했습니다). 방법은 다음과 같습니다.
sigaction()
신호를 포착하고 이전 핸들러를 저장하는 데 사용 합니다. ( android.c : 570 )- 시간이 지나면 세그 폴트가 발생합니다.
- 신호 핸들러에서 마지막으로 한 번 JNI를 호출 한 다음 이전 핸들러를 호출합니다. ( android.c : 528 )
- 해당 JNI 호출에서 유용한 디버깅 정보를 기록
startActivity()
하고 자체 프로세스에 있어야하는 것으로 플래그 지정된 활동을 호출 합니다. ( SGTPuzzles.java:962 , AndroidManifest.xml : 28 ) - 자바에서 돌아와 이전 핸들러를 호출하면 Android 프레임 워크가 연결되어
debuggerd
멋진 네이티브 트레이스를 기록한 다음 프로세스가 종료됩니다. ( debugger.c , debuggerd.c ) - 그 동안 충돌 처리 활동이 시작됩니다. 실제로 5 단계가 완료 될 때까지 기다릴 수 있도록 PID를 전달해야합니다. 나는 이러지 않는다. 여기에서 사용자에게 사과하고 로그를 보낼 수 있는지 묻습니다. 그렇다면 출력을 수집하고 수신자, 제목 및 본문 을 입력
logcat -d -v threadtime
하여 실행합니다ACTION_SEND
. 사용자는 보내기를 눌러야합니다. ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml : 41 - 조심
logcat
실패 또는 몇 초 이상 복용. T-Mobile Pulse / Huawei U8220이라는 장치를 만났는데, 여기서 logcat은 즉시T
(추적 된) 상태가되고 중단됩니다. ( CrashHandler.java:70 , strings.xml : 51 )
Android가 아닌 상황에서는이 중 일부가 다를 수 있습니다. 자신의 고유 한 추적을 수집해야합니다. 보유한 libc의 종류에 따라 다른 질문을 참조하십시오 . 추적 덤프를 처리하고 별도의 크래시 처리기 프로세스를 시작하고 플랫폼에 적합한 방식으로 이메일을 보내야하지만 일반적인 접근 방식은 여전히 작동 할 것이라고 생각합니다.
나는 늦게 조금 해요,하지만 난 똑같은 필요가 있고, 나는 (공통 충돌을 잡기에 의해, 그것을 해결하기 위해 작은 라이브러리를 개발 한 SEGV
, SIBGUS
내부 등) JNI 코드 , 정기적으로 교체 java.lang.Error
예외 . 보너스로 클라이언트가 Android> = 4.1.1
에서 실행중인 경우 스택 추적은 크래시 의 해결 된 역 추적 (전체 네이티브 스택 추적을 포함하는 의사 추적)을 포함합니다. 악의적 인 충돌 (예 : 할당자를 손상시키는 경우)에서 복구 할 수는 없지만 최소한 대부분 의 경우 복구 할 수 있어야 합니다. (성공 및 실패를보고하십시오. 코드는 새로운 것입니다)
More info at https://github.com/xroche/coffeecatch (code is BSD 2-Clauses license)
FWIW, Google Breakpad works fine on Android. I did the porting work, and we're shipping it as part of Firefox Mobile. It requires a little setup, since it doesn't give you stack traces on the client-side, but sends you the raw stack memory and does the stack walking server-side (so you don't have to ship debug symbols with your app).
In my limited experience (non-Android), SIGSEGV in JNI code will generally crash the JVM before control is returned to your Java code. I vaguely recall hearing about some non-Sun JVM which lets you catch SIGSEGV, but AFAICR you can't expect to be able to do so.
You can try to catch them in C (see sigaction(2)), although you can do very little after a SIGSEGV (or SIGFPE or SIGILL) handler as the ongoing behaviour of a process is officially undefined.
'program story' 카테고리의 다른 글
전체 서비스를 다시 시작하지 않고 Tomcat 웹앱을 어떻게 업데이트합니까? (0) | 2020.09.08 |
---|---|
브라우저 확대 / 축소 수준 변경 (0) | 2020.09.08 |
Visual Studio의 개발자 별 app.config / web.config 파일 (0) | 2020.09.08 |
Ido 모드가 너무 똑똑합니다. 파일 이름을 완성하지 못하도록 할 수 있습니까? (0) | 2020.09.08 |
HTML5 (0) | 2020.09.08 |