반응형

안녕하세요. Simple& Happy Dev입니다.

 

앱 개발할 때 ANR, App crash, Native crash 등 많은 오류를 만납니다.

 

오류 발생할 때 빠른 로그 확보는 유의미한 오류 발생 직전 로그를 많이 확보할 수 있도록 합니다.

 

이번 글에서는 오류 발생할 때 빠른 버그 리포팅을 위해서 어떤 준비를 하면 좋은지와 이전 오류 정보들을 보관하고 있는 tombstone과 dropbox를 알아보도록 하겠습니다.

 

빠른 버그 리포팅을 위한 준비

 

- 전원 메뉴에 [버그 신고 버튼 추가] 하기

"설정 - 개발자 옵션 - 버그 신고 바로가기"를 활성화하면 전원 버튼을 누르면 메뉴에 버그 리포트 생성할 수 있는 메뉴가 생깁니다.

 

오류 발생할 때 전원버튼을 누르고, "버그 보고서 작성 또는 버그 신고"를 누르면, 버그 리포트가 생성됩니다.

 

 

 

이는 오류 발생할 때 버그 리포트 생성 메뉴 이동 단계를 줄여줍니다.

 


 

- 삼성 단말의 경우 SYSDUMP로 버그 리포트 생성할 때 [NOTIBAR RUN DUMPSTATE: ON] 하기

 

 

오류 발생할 때 알림창을 내려서 "Run DumpState"를 누르면, 버그 리포트가 생성됩니다.

 

 

이것도 오류 발생시 버그 리포트 생성 메뉴 이동 단계를 줄여줍니다.

 


 

- 삼성 단말의 경우 SYSDUMP로 버그 리포트 생성할 때 [Modem Log 제외] 하기

 

 

일반적으로 앱 개발에서는 Modem 로그가 필요하지 않습니다. 불필요한 시간을 줄일 수 있습니다.

 

Sysdump에 관한 추가 설명은 아래 참고하세요.

2018/11/30 - Bugreport 및 Sysdump (Samsung) 사용 방법

 

 

이전 오류 정보가 기록된 tombstone과 dropbox

 

오류가 발생했으나 버그 리포트를 생성하지 않고 넘어간 경우라도 이후에 확인하는 방법이 있습니다.

 

[tombstone]

tombstone의 경우에 주로 native crash 발생할 때 정보(abort message, register, backtrace, stack, memory map)가 저장됩니다.

 

※native crash가 tombstone에 기록되는 과정은 아래 dropbox의 native crash 내용을 참조하시길 바랍니다.

 

#define MAX_TOMBSTONES  10
#define TOMBSTONE_DIR   "/data/tombstones"
#define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")

 

tombstones 디렉터리(/data/tombstones)는 eng 또는 userdebug 빌드된 단말에서만 접근이 가능합니다.

tombstones 디렉터리를 열어보면 tombstone_xx 파일들을 확인할 수 있습니다.

기본적으로 10개 파일이 저장되게 되어 있고, 10개 이후는 가장 오래된 파일부터 지워지면서 추가됩니다.

 

아래는 userdebug 빌드된 단말에서 보이는 tombstone 디렉터리입니다. user 빌드된 단말에서는 아래가 보이지 않습니다.

  

 

tombstone_xx 파일을 열면 아래처럼 abort message 및 register, backtrace, stack 등의 정보를 확인할 수 있습니다.

pid: 8671, tid: 8785, name: RenderThread  >>> com.sec.android.app.sbrowser <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'Failed to set damage region on surface 0xcefee7e0, error=EGL_BAD_ACCESS'
    r0 00000000  r1 00002251  r2 00000006  r3 00000008
    r4 000021df  r5 00002251  r6 cbdb8f08  r7 0000010c
    r8 cbdb97d0  r9 00003e98  sl cbdb97f0  fp cbdb97e0
    ip 00000000  sp cbdb8ef8  lr f12a44d7  pc f12d580c  cpsr 200f0010
    d0  5f4441425f4c4741  d1  6765722065676143
    d2  0000000000000043  d3  000003e800000045
    d4  0000000000000008  d5  0000000000000000
    d6  00000000d1946020  d7  00000000d1946028
    d8  0000000000000000  d9  0000000000000000
    d10 0000000000000000  d11 0000000000000000
    d12 0000000000000000  d13 0000000000000000
    d14 0000000000000000  d15 0000000000000000
    d16 2e74736973726570  d17 2e6761742e676f6c
    d18 0000000000956d20  d19 00000000005d11e8
    d20 0000000000000000  d21 0000000000000000
    d22 0000000000000000  d23 0000000000000000
    d24 0000005b0000001b  d25 0000005b000000db
    d26 0000000000000000  d27 0000000000000000
    d28 0000000000000000  d29 0000000000000000
    d30 0000000000000000  d31 0000000000000000
    scr 20000013

backtrace:
    #00 pc 0004b80c  /system/lib/libc.so (tgkill+12)
    #01 pc 0001a4d3  /system/lib/libc.so (abort+54)
    #02 pc 00006683  /system/lib/liblog.so (__android_log_assert+154)
    #03 pc 0003a37d  /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread10EglManager11damageFrameERKNS1_5FrameERK6SkRect+204)
    #04 pc 00038405  /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread14OpenGLPipeline4drawERKNS1_5FrameERK6SkRectS8_RKNS0_12FrameBuilder13LightGeometry

EPNS0_16LayerUpdateQueueERKNS0_4RectEbRKNS0_15BakedOpRenderer9LightInfoERKNSt3__16vectorINS_2spINS0_10RenderNodeEEEN

SM_9allocatorISQ_EEEEPNS0_19FrameInfoVisualizerE+32)
    #05 pc 00036dd5  /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread13CanvasContext4drawEv+144)
    #06 pc 00039457  /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread13DrawFrameTask3runEv+138)
    #07 pc 0003e0a3  /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread12RenderThread10threadLoopEv+166)
    #08 pc 0000d479  /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+144)
    #09 pc 000a2c69  /system/lib/libandroid_runtime.so (_ZN7android14AndroidRuntime15javaThreadShellEPv+80)
    #10 pc 00048a89  /system/lib/libc.so (_ZL15__pthread_startPv+24)
    #11 pc 0001b34f  /system/lib/libc.so (__start_thread+32)

stack:
         cbdb8eb8  ffffffdf
         cbdb8ebc  00000000
         cbdb8ec0  cbdb97e0
         cbdb8ec4  76d298d5  /dev/ashmem/dalvik-non moving space_4285_4285 (deleted)
         cbdb8ec8  000021df
         cbdb8ecc  f2ceeaab  /system/bin/app_process32 (sigprocmask+182)
         cbdb8ed0  c60348a0  [anon:libc_malloc]

 

tombstone 추출하는 방법

eng 또는 userdebug 빌드된 단말에서는 adb pull 명령으로 파일을 꺼낼 수 있습니다. (adb pull /data/tombstones)

 

user 빌드된 단말(양산 단말)에서는 "버그 리포트 생성"하면 아래처럼 버그 리포트에 포함돼 나옵니다.

 

[dropbox]

보통 logcat 같은 경우 정해진 크기의 링 버퍼에 로그가 저장되지만, dropbox는 파일로 저장되는 로그입니다.

 

주로 오류나 시스템에 영향을 줄 수 있는 상황을 기록하는 용도로 많이 사용됩니다.

strictmode violation, watchdog, wtf(What a Terrible Failure), netstats_error, lowmem 정보도 기록되지만 여기에서는 ANR과 Crash에 대한 것만 확인하도록 하겠습니다.

 

dropbox 디렉토리(/data/system/dropbox)도 eng 또는 userdebug 빌드된 단말에서만 접근이 가능합니다.

 

아래는 userdebug 빌드된 단말에서 보이는 dropbox 디렉터리입니다. user 빌드된 단말에서는 아래가 보이지 않습니다.

 

ANR

inputsystem에서는 입력 시 5초내 응답이 없을 경우 ANR 트리거 동작해서 AMS(ActivityManagerService)의 inputDispatchingTimeOut을 호출하고, 여기서 다시 AppErrors를 호출해서 ANR 다이얼로그를 화면에 표시하기 전에 Process 정보, ANR reason, 각 프로세스의 CPU 사용량, stack trace 등은 dropbox에 기록(addErrorToDropBox)하고 일부 정보는 로그로 출력합니다.

 

AppErrors.java

 

App Crash

Exception이 Throw 된 후 catch 되지 않으면 Runtime에서 uncaught exception으로 처리합니다.

uncaughtException()에서 AMS의 handleApplicationCrash() -> handleApplicationCrashInner() 이벤트 로그에 Crash 정보 출력 후 dropbox에 기록(addErrorToDropBox) 후 해당 앱을 강제 종료 처리합니다.

 

RuntimeInit.java

 

ActivityManagerService.java

 

 

Native crash

Native crash가 발생하면 커널은 해당 시그널을 보내고, linker 모듈의 debugger(클라이언트)에서 시그널(SIGABRT, SIGSEGV, SIGFPE 등)를 잡아서 debuggerd(데몬 서버)로 DEBUGGER_ACTION_CRASH 메시지를 보냅니다.

 

데몬 서버인 debuggerd에서는 DEBUGGER_ACTION_CRASH 메시지를 받아서 Native에서 보낸 정보를 읽어오고, AMS(ActivityManagerService) NativeCrashListener에 소켓 연결을 설정하고 tombstone를 호출해서 tombstone에 native crash에 대해서 덤프하도록 요청합니다. 이후 dump thread에 의해서 tombstone에 backtrace 외 정보들이 저장됩니다.

 

한편, debuggerd와 소켓 연결된 NativeCrashListener는 스레드를 상속받은 클래스인데, 애초부터 SystemServer에서 AMS로 NativeCrashListener의 인스턴스를 생성해서 스레드로 동작중인 상태였으며, debuggerd에서는 tombstone에 dump를 요청한 이후 NativeCrashListener에도 시그널을 전달해서 아래와 같이 dropbox에 기록하도록 요청합니다.

 

NativeCrashListener.java

 

ActivityManagerService.java

 

dropbox 추출하는 방법

eng 또는 userdebug 빌드된 단말에서는 adb pull 명령으로 파일을 꺼낼 수 있습니다. (adb pull /data/system/dropbox)

 

user 빌드된 단말에서는 tombstone에서 "버그 리포트 생성"을 해서 꺼낸 것처럼 dropbox를 꺼낼 수 없습니다.

단, 삼성 단말의 경우 "Sysdump로 버그 리포트 생성"하면 dropbox 디렉터리에 있는 파일들을 압축해서 내보내줍니다.

 

직전의 오류의 경우에 대해서는 아래 명령으로 꺼낼 수는 있습니다.

 

ANR

adb shell dumpsys dropbox --print system_app_anr > system_app_anr.txt

adb shell dumpsys dropbox --print data_app_anr > data_app_anr.txt

 

APP Crash

adb shell dumpsys dropbox --print system_app_crash > system_app_crash.txt 

adb shell dumpsys dropbox --print data_app_crash > data_app_crash.txt 

 

Native Crash

adb shell dumpsys dropbox --print system_app_native_crash > system_app_native_crash.txt 

adb shell dumpsys dropbox --print data_app_native_crash > data_app_native_crash.txt

 

여기까지입니다. 읽어주셔서 감사합니다.

반응형

안녕하세요. Simple& Happy Dev입니다.

 

이번 글은 Bugreport와 Sysdump 사용방법에 대해서 적어보겠습니다.

 

먼저 Bugreport와 Sysdump는 시스템, 프레임워크, 앱 등의 여러 컴포넌트에 발생한 오류나 오동작에 대해서 향후 분석을 위해서 시스템의 상태나 로그, 기타 정보들을 기록하는 역할을 합니다.

 

문제에 대한 재현 경로가 확실한 경우에는 상관없지만, 문제 재현이 어려운 경우에는 Bugreport나 Sysdump에 의존해서 분석을 해야 합니다.

 

Sysdump는 삼성에서 Bugreport를 커스터마이징한 것으로 생각하면 됩니다. 또한, 삼성 폰에서도 Bugreport를 지원합니다.

 

그럼, 각각의 사용 방법을 알아보겠습니다.

 

[Bugreport]

https://developer.android.com/studio/debug/bug-report

 

위 링크에설명이 있습니다만, 좀 더 자세하게 실제 폰의 스크린샷 첨부해서 설명하겠습니다..

 

Bugreport의 경우 개발자 옵션 메뉴에 있습니다.

(개발자 옵션 메뉴가 안 보이면, 설정 - 소프트웨어 정보 - 빌드번호 7번 누름)

 

개발자 옵션 - 전원 버튼 메뉴에 버그 신고 포함 (On)

 

 - 이렇게 설정한 상태에서 테스트하다가 오류 등이 발생할 경우 전원(Power)키를 누르면 아래와 하단에 "버그 보고서 작성" 버튼이 나오는데, 눌러주면 Bugreport가 동작합니다. (1)

 - Bugreport가 동작하게 되면 산출물을 생성하면서 알림창에 진행 상황이 표시됩니다. (2)

 - Bugreport 알림창에서 (v)를 누르면 메뉴가 표시됩니다. (3)

 - 메뉴에서 세부정보를 누르면 파일명과 버그의 제목과 요약을 적어 넣을 수 있는 창이 나옵니다. (4)

 - Bugreport 진행 상황이 완료가 되면, 알림창을 눌러서 공유할 수 있습니다. (5)

 

  

 

 

 

저장된 Bugreport는 "bugreport-생성일자.txt" 파일이 LOCAT 및 각종 정보들을 포함한 주요 분석 대상입니다.

 

[Sysdump]

전화 앱의 다이얼화면에서 키스트링으로 Sysdump 진입할 수 있습니다.

*#9900#을 누르면 아래와 같은 화면이 나옵니다. 메뉴가 많아서 스크롤하면 추가로 더 보입니다.

 

주의: 혹 아래 앱 개발자가 사용하는 2가지 외에 다른 부분을 건드리고자 하면 먼저 Sysdump의 초기 메뉴값을 스크린샷으로 남겨두시길 바랍니다. 나중에 상태를 변경하고나서 초기 상태로 돌리지 않고 계속 유지하게 되면 문제가 될 수 있습니다.

그리고, 일부 메뉴의 설정이 적용되려면 재부팅이 필요한 경우도 있습니다.

 

 

 

앱을 테스트하기 전에 /log 디렉터리를 삭제하고, DELETE DUMPSTATE/LOGCAT을 누른 이후에 테스트를 진행합니다.

 

앱 개발자의 경우 ①, ② 순서대로 눌러주시면 됩니다.

RUN DUMPSTATE/LOGCAT => COPY TO SDCARD(INCLUDE CP RAMDUMP)

 

실행 시 산출물이 덤프된 상태로 존재합니다. 아직 파일 저장 전입니다. 

실행 시 폰 내부 저장 공간에 파일로 저장됩니다.

 

파일로 생성된 산출물은 /log 디렉터리에 생성됩니다.

 

"dumpState_버전명_생성일자.log" 파일이 Bugreport의 형식과 유사한 산출물이고 주요 분석대상입니다.

 

그 외에 산출물들은 단말 플랫폼 개발 시 필요한 부분이 많고, 앱 개발자에게 필요한 부분은 거의 없습니다.

 

기타 메뉴에 대한 설명

RUM DUMPSTATE/LOGCAT/MODEM LOG : 의 산출물 + CP(MODEM) 정보, 산출물이 파일로 바로 저장됩니다.

 

DELETE DUMPSTATE/LOGCAT현재 덤프된 산출물을 삭제합니다.

 

COPY TO EXTERNAL SDCARD(INCLUDE CP RAMDUMP) : 산출물을 외부 SDCARD에 파일로 저장합니다.

 

DEBUG LEVEL ENABLED : 초기값은 MID, DEBUG LEVEL을 설정합니다. (MID / LOW 선택) 설정 변경 시 재부팅됩니다.

 

TRANSLATION ASSISTANT : 초기값은 OFF, 활성화 시 HierachyViewer에 추가 정보가 나옵니다. 미확인 상태입니다.

 

CP RAM LOGGING : 초기값은 OFF, CP 로깅 관련한 것인데, 누르면 재부팅됩니다.

                             앱 개발자와 관련되는 부분이 아니기에 건드리지 않는게 좋습니다.

 

ENABLE SECLOG : 초기값은 DISABLE, 삼성 내부적으로 사용하는 로그에 대한 출력 여부 설정입니다.

                            활성화 전에 나오지 않던 일부 로그가 출력됩니다. 일반적으로 앱 개발자에게는 의미가 없습니다.
                            팝업에 개인정보가 나올 수 있다고 하니 건드리지 않는 게 좋습니다. 변경 시 재부팅 해야 적용됩니다.

 

NOTIBAR RUN DUMPSTATE : 초기값은 OFF, 활성화 시 Bugreport 처럼 알림창에서 누르면 DUMPSTATE/LOGCAT/CP

                                           산출물이 덤프 됩니다. 실행 시 log 폴더에 파일들로 저장됩니다.

 

MEDIA DB DUMP : Media DB를 덤프합니다.  실행시 log 폴더에 MediaDbDump_?.tar.gz 이름으로 압축해서 저장됩니다.

 

CP(MODEM) 관련해서는 건드리지 않는 게 좋습니다. 여기에 있는 메뉴들은 외부 앱 개발자를 위한 것보다는 폰을 개발하면서 디버깅이나 양산 이후 단말에 대한 분석을 위한 목적이기에 앞서 주의에도 언급했지만, 초기값과 다르게 변경해서 유지할 경우에 폰이 최적의 상태가 아니라서 성능이나 소모전류에 미세한 영향을 줄 수가 있습니다.

 

읽어주셔서 감사합니다.

+ Recent posts