Microsoft MVP성태의 닷넷 이야기
디버깅 기술: 5.16. ASP.NET 디버깅 환경 구성 [링크 복사], [링크+제목 복사],
조회: 37839
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
부모글 보이기/감추기
(연관된 글이 2개 있습니다.)

14.1 ASP.NET 디버깅 환경 구성


[환경 : Windows 2003 기준]
".NET 예외 처리 정리"에서 다뤘던 ASP.NET의 예외처리 핸들러에 대해서 좀 더 다뤄보겠습니다.

일단, 예외를 발생시키는 예제를 다음과 같이 했다는 가정하에 진행해 보겠습니다.

public partial class temp_Exception2nd : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(_threadCallback);
    }

    private void _threadCallback(object state)
    {
        throw new ApplicationException("TEST");
    }
}

말씀드린 것처럼 Request를 처리하지 않는 그 이외의 스레드에서 발생한 예외는 이벤트 로그에 그다지 도움이 되는 유형으로 남지는 않습니다. 물론 이러한 이벤트도 aspnet.config 파일의 legacyUnhandledExceptionPolicy[@enabled] 값을 false로 했을 때에 받게 되는데요. 기본적으로는 다음과 같은 식의 예외에 대한 이벤트 로그가 "Application" 부분에 남게 됩니다.

이벤트 형식:	오류
이벤트 원본:	.NET Runtime 2.0 Error Reporting
이벤트 범주:	없음
이벤트 ID:	5000
날짜:		2006-09-16
시간:		오후 4:49:14
사용자:		N/A
컴퓨터:	 XXXXXXXXXX
설명:
EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.1830, P3 42435be1, P4 app_web_lyd_mjmn, P5 0.0.0.0, P6 450ba011, P7 4, P8 a, P9 system.applicationexception, P10 NIL.

자세한 정보는 http://go.microsoft.com/fwlink/events.asp에 있는 도움말 및 지원 센터를 참조하십시오.
데이터:
0000: 63 00 6c 00 72 00 32 00   c.l.r.2.
0008: 30 00 72 00 33 00 2c 00   0.r.3.,.
0010: 20 00 77 00 33 00 77 00    .w.3.w.
0018: 70 00 2e 00 65 00 78 00   p...e.x.
0020: 65 00 2c 00 20 00 36 00   e.,. .6.
0028: 2e 00 30 00 2e 00 33 00   ..0...3.
0030: 37 00 39 00 30 00 2e 00   7.9.0...
0038: 31 00 38 00 33 00 30 00   1.8.3.0.
0040: 2c 00 20 00 34 00 32 00   ,. .4.2.
0048: 34 00 33 00 35 00 62 00   4.3.5.b.
0050: 65 00 31 00 2c 00 20 00   e.1.,. .
0058: 61 00 70 00 70 00 5f 00   a.p.p._.
0060: 77 00 65 00 62 00 5f 00   w.e.b._.
0068: 6c 00 79 00 64 00 5f 00   l.y.d._.
0070: 6d 00 6a 00 6d 00 6e 00   m.j.m.n.
0078: 2c 00 20 00 30 00 2e 00   ,. .0...
0080: 30 00 2e 00 30 00 2e 00   0...0...
0088: 30 00 2c 00 20 00 34 00   0.,. .4.
0090: 35 00 30 00 62 00 61 00   5.0.b.a.
0098: 30 00 31 00 31 00 2c 00   0.1.1.,.
00a0: 20 00 34 00 2c 00 20 00    .4.,. .
00a8: 61 00 2c 00 20 00 73 00   a.,. .s.
00b0: 79 00 73 00 74 00 65 00   y.s.t.e.
00b8: 6d 00 2e 00 61 00 70 00   m...a.p.
00c0: 70 00 6c 00 69 00 63 00   p.l.i.c.
00c8: 61 00 74 00 69 00 6f 00   a.t.i.o.
00d0: 6e 00 65 00 78 00 63 00   n.e.x.c.
00d8: 65 00 70 00 74 00 69 00   e.p.t.i.
00e0: 6f 00 6e 00 20 00 4e 00   o.n. .N.
00e8: 49 00 4c 00 0d 00 0a 00   I.L.....


이벤트 형식:	오류
이벤트 원본:	VsJITDebugger
이벤트 범주:	없음
이벤트 ID:	4096
날짜:		2006-09-16
시간:		오후 6:29:22
사용자:		NT AUTHORITY\SYSTEM
컴퓨터:	XXXXXXXXXX
설명:
An unhandled exception ('System.ApplicationException') occurred in w3wp.exe [392]. 
Just-In-Time debugging this exception failed with the following error: 
Debugger could not be started because no user is logged on.

Check the documentation index for 'Just-in-time debugging, errors' for more information.

자세한 정보는 http://go.microsoft.com/fwlink/events.asp에 있는 도움말 및 지원 센터를 참조하십시오.
데이터:
0000: 02 00 5c 80               ..\


보시면, 뭐 그다지 아주 쓸모없는 이벤트 로그는 아닙니다. 오류가 발생한 DLL의 이름도 "app_web_lyd_mjmn"라고 나오지요. 이 파일은 "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files" 폴더 하위에서 찾아 볼 수 있습니다.
어쨌든, 이와 같은 오류 발생은 처리되지 않은 예외이기 때문에 w3wp.exe 파일은 예기치 않게 종료가 되어버려서 뒤이어, "System" 부분에서는 다음과 같은 이벤트 로그가 남게 됩니다.

이벤트 형식:	경고
이벤트 원본:	W3SVC
이벤트 범주:	없음
이벤트 ID:	1011
날짜:		2006-09-16
시간:		오후 4:49:21
사용자:		N/A
컴퓨터:	XXXXXXXXXX
설명:
응용 프로그램 풀 'DefaultAppPool'에 사용되는 프로세스에 World Wide Web 게시 서비스와의 심각한 통신 오류가 있습니다. 
프로세스 ID는 '1760'입니다. 데이터 필드에 오류 번호가 있습니다.

자세한 정보는 http://go.microsoft.com/fwlink/events.asp에 있는 도움말 및 지원 센터를 참조하십시오.
데이터:
0000: 6d 00 07 80               m..

여기까지, asp.net에서 별도의 스레드 동작 시에 예외가 발생한 경우의 이벤트 로그에 대한 설명을 마치고.



실제로, 이러한 오류가 발생했을 때 특이한 점은 "DW20.exe"가 작업관리자에 나타나게 되고 이때의 CPU 사용률은 약 100%까지 올라가게 됩니다. 아래의 그림은 위와 같은 오류가 발생했을 때의 CPU 사용률을 보여주고 있습니다.

DW20.exe CPU 사용률

왜냐하면, 이때 시스템은 DW20.exe를 사용해서 예외가 발생한 상황의 w3wp.exe에 대한 덤프 파일을 받아놓기 때문입니다. 실제로, 이런 상황이 발생한 이후에 "C:\WINDOWS\PCHEALTH\ERRORREP" 폴더에 가보면, 그 하위에 덤프 파일을 포함하고 있는 "CAB" 파일이 들어있는 폴더를 발견할 수 있습니다. 예를 들어, 위와 같은 예외 테스트와 함께 제 컴퓨터에는 다음과 같은 경로의 예외 파일이 생성되었습니다.

C:\WINDOWS\PCHEALTH\ERRORREP\QSignoff
				A7233A5.cab
				A7233A5.txt

위의 "A7233A5.cab" 파일의 압축을 풀면 다음과 같이 덤프 파일을 포함하고 있는 것을 확인할 수 있습니다.

mdmpmem.hdmp
version.txt
w3wp.exe.mdmp

여기서 w3wp.exe.mdmp 파일은 .NET 디버깅과 관련된 sos.dll을 사용하는 경우에는 그다지 도움이 되지 않습니다. 따라서 Heap 정보와 함께 덤프가 된 HDMP 확장자의 파일을 가지고 디버깅을 하는 것이 좋습니다.
그런데, VS.NET의 경우 hdmp 확장자를 지원하지 않기 때문에, "mdmpmem.hdmp" 파일을 "mdmpmem.dmp" 파일로 이름을 변경한 다음 더블 클릭을 하면 VS.NET 2005가 로드되면서 덤프 파일을 읽게 됩니다. 물론, 그 이후에 "F5" 버튼을 누르게 되면 정상적으로 디버깅이 가능합니다. 이에 대한 자세한 내용은 다음의 토픽을 참조하십시오.

3.5.1 VS.NET 2005를 이용한 미니덤프 파일 분석 (1)
; https://www.sysnet.pe.kr/2/0/318

3.5.2 VS.NET 2005를 이용한 미니덤프 파일 분석 (2)
; https://www.sysnet.pe.kr/2/0/319


이 덤프 파일 관리에 대해서 주의하셔야 할 것이 있는데요. "C:\WINDOWS\PCHEALTH\ERRORREP\" 폴더에 있는 것들은 영구적으로 남지 않는 다는 것이 문제입니다. 이들은 "Error Reporting Service" NT 서비스에 의해서 처리(전송)가 되고 나면 삭제되어집니다.



ASP.NET에서의 예외 처리에 대한 문제 해결을 위해서 위와 같이 시스템이 자동적으로 남겨주는 덤프 파일을 사용하는 것도 좋은 방법이지만, 만약 그 예외가 빈번하게 발생하는 상황이라면 CPU 100% 사용률과 함께 덤프 파일이 남겨지는 것은 여간 부담스러운 일이 아닐 수 없습니다. 가능하다면 이런 상황을 피하는 것이 좋겠는데요. 바로 이런 경우를 위해 ".NET 예외 처리 정리"에서 소개시켜 드렸던 다음의 URL에서 제공하는 방법이 권장되어집니다.

Unhandled exceptions cause ASP.NET-based applications to unexpectedly quit in the .NET Framework 2.0
; https://docs.microsoft.com/en-us/troubleshoot/aspnet/exceptions-cause-apps-quit

여러분들이 위의 토픽을 보시고 직접 HttpModule을 작성하셔도 되겠지만, 제가 이 토픽에 첨부한 WebLib.Snippet에 이미 코딩을 해놓았으니 그것을 이용하셔도 좋겠습니다. 방법은 간단합니다.

1. WebLib.Snippet.dll 파일을 GAC에 등록.

2. 다음과 같은 내용을 web.config에 등록.

===== IIS 6 또는 IIS 7/7.5에서의 Classic Mode =====
<configuration>
	<system.web>
		; [중간 생략]
		<httpModules>
			<add name="UnhandledExceptionModule" 
			type="WebLib.Snippet.UnhandledExceptionModule, WebLib.Snippet, Version=1.0.0.2, Culture=neutral, PublicKeyToken=f9e203bf2db94124" />
		</httpModules>
	</system.web>
</configuration>

===== IIS 7/7.5에서의 Integrated Mode =====
<configuration>
  <system.webServer>
    <modules>
      <add name="UnhandledExceptionModule" type="WebLib.Snippet.UnhandledExceptionModule, WebLib.Snippet, Version=1.0.0.2, Culture=neutral, PublicKeyToken=f9e203bf2db94124"/>
    </modules>
  </system.webServer>
</configuration>

3. "%WINDIR%\Microsoft.NET\Framework\v2.0.50727\Aspnet.config" 파일의 legacyUnhandledExceptionPolicy 값을 다음과 같이 true로 변경.

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <runtime>
        <legacyUnhandledExceptionPolicy enabled="true" />
        <legacyImpersonationPolicy enabled="true"/>
        <alwaysFlowImpersonationPolicy enabled="false"/>
        <SymbolReadingPolicy enabled="1" />
    </runtime>
</configuration>

4. "iisreset" 실행



위와 같이 설정하고 나서, 이제 다시 예외를 발생시키는 웹폼 페이지를 방문하게 되면 이벤트 로그에는 "Application" 영역에 다음과 같이 하나의 로그만 남게 되고, w3wp.exe는 종료를 하지 않게 됩니다. 물론 덤프 파일 처리도 하지 않게 되어 CPU 사용률이 올라가는 일도 없습니다.

이벤트 형식:	오류
이벤트 원본:	ASP.NET 2.0.50727.0
이벤트 범주:	없음
이벤트 ID:	0
날짜:		2006-09-16
시간:		오후 6:47:48
사용자:		N/A
컴퓨터:	XXXXXXXXXX
설명:
이벤트 ID( 0 )(원본 ( ASP.NET 2.0.50727.0 )에 있음)에 대한 설명을 찾을 수 없습니다. 
로컬 컴퓨터에 원격 컴퓨터에서 보낸 메시지를 표시하기 위해 필요한 레지스트리 정보 또는 메시지 DLL 파일이 없을 수 있습니다. 
이 설명을 검색하는 데 /AUXSOURCE= 플래그를 사용할 수 있습니다. 자세한 정보는 도움말 및 지원을 참조하십시오. 
다음 정보는 이벤트의 일부입니다. 

UnhandledException logged by UnhandledExceptionModule.dll:

appId=/LM/W3SVC/1/ROOT

type=System.ApplicationException

message=TEST

stack=
   위치: temp_Exception2nd._threadCallback(Object state) 파일 d:\...\Exception2nd.aspx.cs:줄 22
   위치: System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
   위치: System.Threading.ExecutionContext.runTryCode(Object userData)
   위치: System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   위치: System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   위치: System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   위치: System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)

PDB 파일 구성만 제대로 해주시면 위와 같이 실제 예외가 발생한 소스 파일명과 라인 번호까지 얻을 수 있습니다.



[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 12/2/2022]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2008-10-09 09시58분
Watson Bucket 정보를 이용한 CLR 응용 프로그램 예외 분석
; http://www.sysnet.pe.kr/2/0/595
kevin25

... 61  62  63  64  65  66  67  68  69  70  [71]  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12162정성태2/26/202021857디버깅 기술: 166. C#에서 만든 COM 객체를 C/C++로 P/Invoke Interop 시 메모리 누수(Memory Leak) 발생 [6]파일 다운로드2
12161정성태2/26/202017909오류 유형: 597. manifest - The value "x64" of attribute "processorArchitecture" in element "assemblyIdentity" is invalid.
12160정성태2/26/202018257개발 환경 구성: 469. Reg-free COM 개체 사용을 위한 manifest 파일 생성 도구 - COMRegFreeManifest
12159정성태2/26/202015358오류 유형: 596. Visual Studio - The project needs to include ATL support
12158정성태2/25/202017947디버깅 기술: 165. C# - Marshal.GetIUnknownForObject/GetIDispatchForObject 사용 시 메모리 누수(Memory Leak) 발생파일 다운로드1
12157정성태2/25/202017980디버깅 기술: 164. C# - Marshal.GetNativeVariantForObject 사용 시 메모리 누수(Memory Leak) 발생 및 해결 방법파일 다운로드1
12156정성태2/25/202016558오류 유형: 595. LINK : warning LNK4098: defaultlib 'nafxcw.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
12155정성태2/25/202016013오류 유형: 594. Warning NU1701 - This package may not be fully compatible with your project
12154정성태2/25/202015393오류 유형: 593. warning LNK4070: /OUT:... directive in .EXP differs from output filename
12153정성태2/23/202019515.NET Framework: 898. Trampoline을 이용한 후킹의 한계파일 다운로드1
12152정성태2/23/202018571.NET Framework: 897. 실행 시에 메서드 가로채기 - CLR Injection: Runtime Method Replacer 개선 - 세 번째 이야기(Trampoline 후킹)파일 다운로드1
12151정성태2/22/202019362.NET Framework: 896. C# - Win32 API를 Trampoline 기법을 이용해 C# 메서드로 가로채는 방법 - 두 번째 이야기 (원본 함수 호출)파일 다운로드1
12150정성태2/21/202019616.NET Framework: 895. C# - Win32 API를 Trampoline 기법을 이용해 C# 메서드로 가로채는 방법 [1]파일 다운로드1
12149정성태2/20/202018418.NET Framework: 894. eBEST C# XingAPI 래퍼 - 연속 조회 처리 방법 [1]
12148정성태2/19/202020948디버깅 기술: 163. x64 환경에서 구현하는 다양한 Trampoline 기법 [1]
12147정성태2/19/202018624디버깅 기술: 162. x86/x64의 기계어 코드 최대 길이
12146정성태2/18/202019374.NET Framework: 893. eBEST C# XingAPI 래퍼 - 로그인 처리파일 다운로드1
12145정성태2/18/202019235.NET Framework: 892. eBEST C# XingAPI 래퍼 - Sqlite 지원 추가파일 다운로드1
12144정성태2/13/202019433.NET Framework: 891. 실행 시에 메서드 가로채기 - CLR Injection: Runtime Method Replacer 개선 - 두 번째 이야기파일 다운로드1
12143정성태2/13/202015995.NET Framework: 890. 상황별 GetFunctionPointer 반환값 정리 - x64파일 다운로드1
12142정성태2/12/202018358.NET Framework: 889. C# 코드로 접근하는 MethodDesc, MethodTable파일 다운로드1
12141정성태2/10/202017384.NET Framework: 888. C# - ASP.NET Core 웹 응용 프로그램의 출력 가로채기 [2]파일 다운로드1
12140정성태2/10/202017937.NET Framework: 887. C# - ASP.NET 웹 응용 프로그램의 출력 가로채기파일 다운로드1
12139정성태2/9/202019190.NET Framework: 886. C# - Console 응용 프로그램에서 UI 스레드 구현 방법
12138정성태2/9/202023219.NET Framework: 885. C# - 닷넷 응용 프로그램에서 SQLite 사용 [6]파일 다운로드1
12137정성태2/9/202016439오류 유형: 592. [AhnLab] 경고 - 디버거 실행을 탐지했습니다.
... 61  62  63  64  65  66  67  68  69  70  [71]  72  73  74  75  ...