Windows 앱의 크래시 덤프 수집 입문 - 우선 WER / ProcDump / WinDbg를 어떻게 구분해서 쓸까

· · Windows 개발, 불량 조사, 크래시 덤프, WER, ProcDump, WinDbg

Windows 앱에서 「가끔만 떨어진다」가 시작되면 로그만으로는 따라가기 어려운 장면이 꽤 있습니다.

특히 다음과 같은 경우입니다.

  • 고객 환경에서만 일어난다
  • 예외 메시지는 잡히고 있지만 호출원의 문맥이 부족하다
  • C# / .NET의 managed 쪽뿐만 아니라 COM, P/Invoke, native DLL, vendor SDK가 얽혀 있다
  • 장시간 운전 후에만 떨어진다

이럴 때 효과가 있는 것이 크래시 덤프입니다. 크래시 시점의 프로세스 상태를 파일에 떨어뜨려 두면 예외 코드, 떨어진 스레드의 스택, 로드되어 있던 모듈, 메모리의 일부 또는 전부를 나중에 읽을 수 있습니다.

Windows에서는 먼저 WER의 LocalDumps, 필요에 따라 Sysinternals ProcDump, 더 제어하고 싶어지면 MiniDumpWriteDump를 쓴다는 순서로 생각하는 것이 이해하기 쉽습니다. 이 글에서는 Windows 데스크톱 앱, 상주 앱, Windows 서비스, 장치 연계 도구 등을 전제로 크래시 덤프 수집의 첫걸음을 정리합니다.

1. 먼저 결론

먼저 잡아 두고 싶은 점만 나열합니다.

  • 우선은 WER LocalDumps를 앱 단위로 설정하는 것이 무난합니다. 추가 도구 없이 크래시 후에 로컬에 덤프를 남길 수 있습니다.
  • 재현율 낮은 현장 조사나 first chance exception / hang까지 보고 싶다면 ProcDump를 씁니다.
  • 자체 수집은 마지막에 생각한다 정도로 충분합니다. 필요해진 다음에 MiniDumpWriteDump를 검토하면 충분합니다.
  • 덤프와 같은 정도로 중요한 것이 PDB와 배포 바이너리의 보관입니다. 덤프만 있어도 심볼이 없으면 읽을 수 있는 양이 꽤 줄어듭니다.
  • 풀 덤프는 강하지만 크기와 기밀 정보 혼입 위험도 강합니다. 보관 장소, 보관 수, 접근 권한, 공유 절차를 먼저 정합니다.

입문 단계의 추천 구성은 대체로 다음입니다.

환경 우선의 구성
개발기 / 검증기 WER LocalDumps를 앱 단위로 설정하고 우선 DumpType=2의 풀 덤프
고객 환경 / 현장기 용량과 기밀 요건을 보고 DumpType=1이나 2를 선택. 필요 시에만 ProcDump를 추가
장시간 운전이나 hang 조사 WER에 더해 ProcDump의 -h-e 1을 검토
독자 UI나 첨부 로그도 포함하고 싶다 별도 프로세스 전제로 MiniDumpWriteDump를 쓰는 자체 수집

요컨대 처음은 WER, 다음에 ProcDump, 마지막에 자체 수집입니다. 여기를 역순으로 시작하면 대체로 설계가 무거워집니다.

2. 크래시 덤프로 무엇을 알 수 있는가

크래시 덤프는 「그 순간의 스냅샷」입니다. 방범 카메라라기보다 사고 현장의 정지화면에 가깝습니다.

그래서 다음과 같은 정보는 꽤 취하기 쉽습니다.

  • 어떤 예외 코드로 떨어졌는가
  • 어느 스레드가 떨어졌는가
  • 그 시점의 콜 스택
  • 로드되어 있던 모듈
  • 어느 정도의 메모리를 포함했는지에 따라 힙상의 상태나 객체의 내용

한편으로 다음 같은 것들은 덤프만으로는 부족하기 쉽습니다.

  • 거기에 이르기까지의 시계열
  • 몇 시간 전부터의 증가 경향
  • 통신이나 장치와의 외부 상태
  • 직전의 입력이나 업무 문맥

그래서 실무에서는 덤프만으로 완결하려 하지 않고, 로그나 heartbeat와 조합하는 것이 기본입니다.

3. 수집 방법의 전체상

Windows 앱의 덤프 수집에서 입문 단계에 잡아 두고 싶은 방법은 다음 4가지입니다.

방법 맞는 장면 강점 주의점
WER LocalDumps 우선 상설하고 싶은 크래시 수집 Windows 표준. 앱 단위로 설정하기 쉽다 기본은 크래시 용도. hang이나 세세한 조건 분기는 약하다
ProcDump 재현율 낮은 조사, hang, first chance exception 트리거가 많다. 현장 투입하기 쉽다 외부 도구 운영이 된다
작업 관리자의 덤프 작성 수동으로 지금의 상태를 취하고 싶다 GUI로 그 자리에서 취할 수 있다 자동 수집이 아니다
MiniDumpWriteDump 자체의 진단 기능을 만들고 싶다 첨부 로그나 독자 메타데이터를 맞추기 쉽다 구현을 대충하면 오히려 망가진다

초심자에게 가장 중요한 것은 「무엇으로 취할지」보다 먼저 「어떤 조건에서」, 「어디로」, 「어느 크기로」 취할지를 정하는 것입니다.

4. 처음의 추천은 WER LocalDumps

4.1 먼저 보는 레지스트리 값

Windows Error Reporting (WER)에는 크래시 후에 로컬에 사용자 모드 덤프를 보존하는 LocalDumps가 있습니다. 추가 도구를 배포하지 않아도 되므로, 우선의 한 수로 꽤 다루기 쉽습니다.

기본 키는 다음입니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps

여기에 전역 설정을 둘 수도 있지만 실무에서는 앱 단위의 서브키에 치우치는 편이 다루기 쉽습니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe

처음에 보는 값은 3가지입니다.

의미 우선의 추천
DumpFolder 덤프의 출력 대상 전용 폴더를 둔다
DumpCount 보관 수 5〜10 정도부터
DumpType 0=커스텀, 1=미니, 2=풀 처음은 2, 용량이 엄격하면 1

4.2 앱 단위로 설정하는 예

예를 들어 MyApp.exe에 대해 C:\CrashDumps\MyApp에 풀 덤프를 최대 10개 남기고 싶다면 우선 다음처럼 설정할 수 있습니다.

reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpFolder /t REG_EXPAND_SZ /d "C:\CrashDumps\MyApp" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpCount /t REG_DWORD /d 10 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 2 /f

이 예에서의 포인트는 다음입니다.

  • 전역이 아니라 MyApp.exe로 한정하고 있다
  • 출력 대상을 전용 폴더로 분리하고 있다
  • 우선은 풀 덤프로 하고 있다
  • 보관 수를 10으로 제한하고 있다

4.3 취해졌는지 확인한다

설정을 넣었다면 운영에서 자연 발생을 기다리기 전에 검증 환경에서 반드시 한 번은 취해 보는 편이 안전합니다.

확인 포인트는 다음입니다.

  1. 상정한 폴더에 .dmp가 나오는가
  2. 크기가 운영 상정에 맞는가
  3. WinDbg로 열 수 있는가
  4. Event Viewer의 Application 로그에서 crash가 보이는가

5. ProcDump를 쓰는 장면

WER로 충분한 경우가 많지만 다음 같은 때는 ProcDump가 편리합니다.

  • 레지스트리 상설을 피하고 싶다
  • 이미 기동 중인 프로세스만 감시하고 싶다
  • 다음 기동부터만 감시하고 싶다
  • first chance exception을 보고 싶다
  • hang을 취하고 싶다
  • 퍼포먼스 카운터나 조건부로 취하고 싶다

5.1 자주 쓰는 옵션

입문 단계에서 자주 쓰는 것만으로 좁히면 ProcDump는 다음을 외워 두면 꽤 싸울 수 있습니다.

옵션 의미
-ma 풀 덤프
-mp MiniPlus 덤프
-e 미처리 예외로 덤프
-e 1 first chance / second chance 예외로 덤프
-h 행된 윈도우로 덤프
-w 대상 프로세스의 기동 대기
-x 대상 프로세스를 기동해 감시
-n 최대 덤프 수
-accepteula 초회 EULA 확인을 자동 승낙

5.2 대표적인 커맨드 예

이미 기동 중인 프로세스를 미처리 예외로 풀 덤프

procdump -accepteula -ma -e 1234 C:\CrashDumps\MyApp

다음 기동을 기다리다 미처리 예외로 풀 덤프

procdump -accepteula -ma -e -w MyApp.exe C:\CrashDumps\MyApp

스스로 기동해 그대로 감시

procdump -accepteula -ma -e -x C:\CrashDumps\MyApp MyApp.exe

first chance exception도 취하고 싶다

procdump -accepteula -ma -n 3 -e 1 MyApp.exe C:\CrashDumps\MyApp

행을 취하고 싶다

procdump -accepteula -h MyApp.exe C:\CrashDumps\MyApp

5.3 -i를 첫 한 수로 삼지 않는 이유

ProcDump에는 -i로 postmortem debugger로서 등록하는 사용 방식도 있습니다. 이것은 강력하지만 머신 전체의 크래시 시 동작에 파고들기 때문에 입문 단계의 첫 한 수로는 조금 무겁습니다.

그래서 처음은 WER의 앱 단위 설정이나 ProcDump의 -w / -x / PID 지정부터 들어가는 것이 다루기 쉽습니다.

6. 자체 수집으로 MiniDumpWriteDump를 쓸 때의 사고방식

자체 수집이 맞는 것은 예를 들어 다음 같은 장면입니다.

  • UI에서 「진단 정보를 저장」 버튼을 내고 싶다
  • 덤프와 함께 로그, 설정, 트레이스 ID를 묶고 싶다
  • 관련된 자식 프로세스나 보조 프로세스도 한꺼번에 하고 싶다
  • 업로드 전에 독자 마스킹이나 압축을 넣고 싶다

여기서 중심이 되는 API가 MiniDumpWriteDump입니다.

다만 여기는 조금 버릇이 있습니다. 입문에서 특히 빗나가고 싶지 않은 것은 다음 2점입니다.

  1. 가능하다면 dump 대상과는 별도 프로세스에서 호출한다
  2. DbgHelp 계는 single-threaded 전제로 다룬다

7. 미니 덤프 / 풀 덤프 / 중간 크기의 선택 방법

여기서 헤매는 사람이 꽤 많습니다. 실무에서는 다음처럼 생각하면 정리하기 쉽습니다.

종류 맞는 장면 좋은 점 주의점
미니 덤프 우선 넓게 넣고 싶다, 공유를 가볍게 하고 싶다 작다, 전송하기 쉽다 상태 복원의 깊이는 약하다
풀 덤프 원인 조사를 우선하고 싶다, native 경계나 힙이 의심스럽다 취할 수 있는 정보가 많다 크기가 크다, 기밀 혼입 위험이 높다
MiniPlus / Custom 미니로는 부족하고 풀은 무겁다 밸런스를 잡을 수 있다 조정의 지식이 필요

초심자용 추천은 꽤 단순합니다.

  • 개발기 / 검증기에서는 풀 덤프
  • 고객 환경에서는 미니나 풀을 운영 조건으로 선택
  • 메모리 파괴, 네이티브 DLL, COM, P/Invoke, 장시간 가동 후의 상태 이상이 의심스럽다면 풀 쪽

8. 운영에서 먼저 정해 둘 것

덤프 수집은 구현보다 운영에서 굴러떨어지는 경우가 꽤 있습니다. 먼저 정하고 싶은 것은 다음입니다.

8.1 PDB와 바이너리를 어떻게 남길 것인가

이것이 가장 중요합니다.

  • 배포한 EXE / DLL의 정확한 버전
  • 그 버전에 대응하는 PDB
  • 어느 커밋 / 어느 빌드 파이프라인에서 만들었는가
  • 인스톨러나 배포물의 버전 정보

8.2 어디로 내고 몇 개 남길 것인가

풀 덤프는 꽤 커집니다. 처음부터 다음을 정해 두는 편이 안전합니다.

  • 시스템 드라이브 바로 아래에 두는 채로 하지 않는다
  • 전용 폴더로 분리한다
  • DumpCount-n으로 상한을 끊는다
  • 장기 보관과 일차 보관을 나눈다

8.3 누가 볼 수 있어도 되는가

풀 덤프에는 기밀 정보나 개인 정보가 섞일 가능성이 있습니다.

  • 평문 설정
  • 접속 문자열
  • 토큰이나 자격 정보
  • 직전에 다루고 있던 업무 데이터
  • 파일 경로나 사용자 이름

그래서 「취하는」 설계와 동시에 「누가 만질 수 있는가」도 정할 필요가 있습니다.

9. 취한 뒤의 최단 해석 도선

덤프를 취한 뒤 처음에 할 것은 의외로 소박합니다.

9.1 WinDbg를 넣는다

지금의 WinDbg는 Microsoft Store나 winget으로 넣기 쉬워져 있습니다.

winget install Microsoft.WinDbg

9.2 덤프를 연다

windbg -z C:\CrashDumps\MyApp\MyApp_YYMMDD_HHMMSS.dmp

9.3 심볼을 설정한다

먼저 Microsoft 공개 심볼을 쓸 수 있는 상태로 하고, 그 후 자기 PDB의 위치를 더합니다.

.symfix C:\Symbols\Microsoft
.sympath+ C:\Symbols\MyApp
.reload

9.4 먼저 자동 해석을 본다

!analyze -v

그 위에서,

  • 어떤 예외 코드인가
  • faulting module은 무엇인가
  • 자기 코드가 어디까지 스택에 보이는가
  • 예외 스레드 이외에 의심스러운 대기나 막힘이 없는가

를 순서대로 봅니다.

10. 흔히 빠지는 곳

10.1 덤프는 취해졌지만 PDB가 없다

이것이 꽤 많습니다. 덤프 수집은 성공했어도 읽을 재료가 부족합니다.
수집 설정과 같은 타이밍에 PDB의 보관 설계도 넣는 편이 좋습니다.

10.2 DumpFolder의 ACL을 보지 않았다

서비스나 권한 분리된 프로세스에서는 여기서 헛손질하기 쉽습니다.
「그 프로세스가 정말로 쓸 수 있는가」를 먼저 확인합니다.

10.3 풀 덤프를 운영기의 시스템 드라이브로 계속 낸다

이것은 용량 사고의 단골입니다.
보관 수 제한과 출력 대상 분리는 처음부터 넣습니다.

10.4 WER만으로 hang도 전부 보려고 한다

WER LocalDumps는 우선 crash에 강합니다.
hang이나 first chance exception은 ProcDump 쪽이 맞는 장면이 있습니다.

10.5 -e 1을 상시 넣어 예외의 폭풍이 된다

first chance exception은 편리하지만 평범하게 많습니다.
건수 제한을 붙이고, 짧은 시간만 넣고, 대상을 한정한다가 현실적입니다.

11. 정리

크래시 덤프는 재현율 낮은 장애에 대해 꽤 강한 관측점입니다. 특히 Windows 앱에서 COM, P/Invoke, native DLL, 장시간 운전이 얽힌다면 처음부터 「떨어지면 무엇이 남는가」를 정해 두는 가치가 있습니다.

추천하는 순서는 심플합니다.

  1. 우선 WER LocalDumps를 앱 단위로 넣는다
  2. 필요하다면 ProcDump를 더한다
  3. 더 제어하고 싶어지면 별도 프로세스 전제로 MiniDumpWriteDump를 쓴다

이 순서로 진행하면 크게 빗나가기 어렵습니다.

12. 참고 자료

같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.

Windows 앱이 프로그램 실수에 의한 예외로 떨어져도 확실히 로그를 남기려면 - in-process에 걸지 않는 설계와 WER / 최종 로그 / 감시 프로세스의 베스트 프랙티스

Windows 앱이 예상 밖의 예외로 떨어져도 원인을 추적할 수 있도록, 통상 로그·최종 크래시 마커·WER LocalDumps·감시 프로세스를 어떻게 조합할지를 실무 관점에서 정리하고, in-process 핸들러에 의존하지 않는 설계의 베스트 ...

이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.

이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.

저자 프로필

기사 저자의 프로필 페이지입니다.

Go Komura

합동회사 코무라소프트 대표

Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.

블로그 목록으로 돌아가기