SIGSEGV (세그먼테이션 오류)를 잡고 Android의 JNI에서 스택 추적을 얻으려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/1083154

문제

이동중 프로젝트 새로운 Android Native Development Kit (예 : JNI)와 나는 Sigsegv를 잡고 싶다. 발생 : 프로세스의 즉각적인 무의미한 죽음과 OS가 다시 시작하려는 시도가 가능합니다. (편집하다: JVM/Dalvik VM은 신호를 잡고 스택 추적 및 기타 유용한 정보를 기록합니다. 나는 단지 사용자에게 그 정보를 저에게 이메일로 전송할 수있는 옵션을 제공하고 싶습니다.)

상황은 다음과 같습니다. 내가 쓰지 않은 C 코드의 큰 본문은이 응용 프로그램 (모든 게임 논리)에서 대부분의 작업을 수행하며, 많은 다른 플랫폼에서 잘 테스트되어 있지만 내 Android에서 내가 전적으로 가능합니다. 포트는 쓰레기를 공급하고 기본 코드로 충돌을 일으키기 때문에 현재 Android 로그에 나타나는 충돌 덤프 (네이티브 및 Java)를 원합니다 (Android가 아닌 상황에서는 Stderr라고 생각합니다). 콜백 (JNI에서 나오고 나오는) 숫자는 약 40 명과 분명히 작은 차이에 대한 보너스 포인트에도 불구하고 C와 Java 코드를 모두 임의로 수정할 수 있습니다.

나는 J2SE, libjsig.so의 신호 체인 라이브러리에 대해 들었고 Android에서 그런 신호 핸들러를 안전하게 설치할 수 있다면 내 질문의 일부를 해결할 수 있지만 Android/Dalvik의 그러한 라이브러리는 없습니다. .

도움이 되었습니까?

해결책

편집하다: 젤리 빈에서 스택 추적을 얻을 수 없습니다. READ_LOGS 떠났다. :-(

실제로 너무 이국적인 작업을 수행하지 않고 신호 처리기가 작동했으며이를 사용하여 코드를 공개했습니다. Github에서 (편집 : 역사적 릴리스에 연결; 그 이후로 충돌 핸들러를 제거했습니다). 방법은 다음과 같습니다.

  1. 사용 sigaction() 신호를 잡고 오래된 핸들러를 보관합니다. (Android.c : 570)
  2. 시간이 지나면 segfault가 발생합니다.
  3. 신호 핸들러에서 마지막으로 JNI로 전화 한 다음 이전 핸들러에게 전화하십시오. (Android.c : 528)
  4. 그 jni 호출에서 유용한 디버깅 정보를 기록하고 전화하십시오. startActivity() 자체 프로세스에 있어야하는 것으로 표시되는 활동에. (sgtpuzzles.java:962, AndroidManifest.xml : 28)
  5. Java에서 돌아와서 이전 핸들러를 호출하면 Android 프레임 워크가 연결됩니다. debuggerd 당신을 위해 멋진 기본 추적을 기록하면 과정이 죽을 것입니다. (Debugger.c, Debuggerd.c)
  6. 한편, 당신의 충돌 처리 활동이 시작됩니다. 실제로 5 단계가 완료되기를 기다릴 수 있도록 PID를 전달해야합니다. 나는 이것을하지 않는다. 여기에서 사용자에게 사과하고 로그를 보낼 수 있는지 묻습니다. 그렇다면 출력을 수집하십시오 logcat -d -v threadtime 그리고 시작합니다 ACTION_SEND 수신자, 피험자 및 신체가 채워진 상태에서 사용자는 Send를 누르야합니다. (Crashhandler.java, sgtpuzzles.java:462, strings.xml : 41
  7. 조심하십시오 logcat 실패하거나 몇 초 이상 걸립니다. 나는 하나의 장치 인 t-mobile 펄스 / Huawei U8220을 만났다. T (추적) 상태와 교수형. (Crashhandler.java:70, strings.xml : 51)

비 분리 상황에서는이 중 일부가 다를 것입니다. 당신은 당신의 자신의 원주민 흔적을 모아야합니다. 이 다른 질문, 어떤 종류의 LIBC에 따라. 트레이스 덤프를 처리하고, 별도의 충돌 핸들러 프로세스를 시작하고, 플랫폼에 적합한 방법으로 이메일을 보내야하지만 일반적인 접근 방식이 여전히 작동해야한다고 생각합니다.

다른 팁

조금 늦었지만 똑같은 필요가 있었고 일반적인 충돌을 잡음으로써이를 해결하기 위해 작은 도서관을 개발했습니다 (SEGV, SIBGUS, 내부 JNI 코드, 정기적으로 교체하십시오 java.lang.Error 예외. 보너스, 클라이언트가 Android에서 실행중인 경우> = 4.1.1, 스택 트레이스는 분해 된 것을 포함합니다 백트레이스 충돌의 (전체 기본 스택 트레이스를 포함하는 의사 트레이스). 악의적 인 충돌로부터 회복되지는 않지만 (예를 들어 할당자를 손상시킨 경우), 최소한 복구 할 수 있어야합니다. 대부분 그들의. (성공과 실패를보고하십시오. 코드는 새로운 것입니다)

더 많은 정보 https://github.com/xroche/coffeecatch(코드입니다 BSD 2 클래스 라이센스)

fwiw, Google 브레이크 패드 안드로이드에서 잘 작동합니다. 포팅 작업을 수행했으며 Firefox Mobile의 일부로 배송합니다. 클라이언트면에서 스택 추적을 제공하지 않지만 원시 스택 메모리를 보내고 스택 워킹 서버 측을 수행하므로 약간의 설정이 필요합니다 (따라서 앱으로 디버그 기호를 배송 할 필요가 없습니다. ).

제한된 경험 (비 Android)에서 JNI 코드의 SIGSEGV는 일반적으로 제어가 Java 코드로 반환되기 전에 JVM에 충돌합니다. 나는 당신이 sigsegv를 잡을 수있는 비 Sun JVM에 대해 모호하게 기억하지만, afaicr는 그렇게 할 수 없다고 기대할 수 없습니다.

프로세스의 진행중인 동작이 공식적으로 정의되지 않으므로 Sigsegv (또는 Sigfpe 또는 Sigill) 핸들러 후에는 거의 할 수는 있지만 C에서 CA (Sigaction (2) 참조)를 잡으려고 시도 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top