Microsoft MVP성태의 닷넷 이야기
오류 유형: 102. System.MissingMethodException [링크 복사], [링크+제목 복사],
조회: 28197
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 4개 있습니다.)
System.MissingMethodException

특정 컴퓨터에서 제품 설치 후 w3wp.exe가 죽는다는 보고가 왔습니다. 설치된 환경을 문의하니 정확히 ".NET Framework 2.0"만 설치되고 더 이상 윈도우 업데이트를 받지 않고 있는 사이트임을 알게 되었습니다.

그래서, 동일하게 Virtual PC를 구성하고. (도대체, Virtual PC가 없던 시절에는 다들 어떻게 제품 개발을 했을까나... ^^;)

재현을 해보았더니, 여지없이 이벤트 로그에 고객 사이트에서 발생한 것과 동일한 오류가 떴습니다.

Event Type: Error
Event Source:   .NET Runtime 2.0 Error Reporting
Event Category: None
Event ID:   5000
Date:       8/17/2010
Time:       3:54:48 PM
User:       N/A
Computer:   WIN2K3CLR2
Description:
EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.3959, P3 45d6968e, P4 mscorlib, P5 2.0.0.0, P6 4333ab80, P7 122f, P8 14, P9 system.missingmethodexception, P10 NIL.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
Data:
0000: 63 00 6c 00 72 00 32 00   c.l.r.2.
... [생략] ...
00e0: 20 00 4e 00 49 00 4c 00    .N.I.L.
00e8: 0d 00 0a 00               ....    

위의 "Description"에 있는 정보의 해독은 예전 글에서 소개해 드렸지요.

Watson Bucket 정보를 이용한 CLR 응용 프로그램 예외 분석
; https://www.sysnet.pe.kr/2/0/595

우선, MethodDef == 122f임을 알고 있으니 ILDASM.exe에서 다음과 같이 찾아낼 수 있습니다. (반드시, CLR 2.0만 설치된 mscorlib.dll을 검사해야 합니다.)

TypeDef #335 (02000150)
-------------------------------------------------------
    TypDefName: System.Threading.ThreadHelper  (02000150)
    Flags     : [NotPublic] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit]  (00100000)
    Extends   : 02000002 [TypeDef] System.Object

...[생략]...

    Method #3 (0600122f) 
    -------------------------------------------------------
        MethodName: ThreadStart_Context (0600122F)
        Flags     : [Assem] [Static] [HideBySig] [ReuseSlot]  (00000093)
        RVA       : 0x00032628
        ImplFlags : [IL] [Managed]  (00000000)
        CallCnvntn: [DEFAULT]
        ReturnType: Void
        1 Arguments
            Argument #1:  Object
        1 Parameters
            (1) ParamToken : (0800192e) Name : state flags: [none] (00000000)

오호... ThreadStart_Context 메서드에서 무슨 일이 있었던 걸까요? 문제가 발생한 IL Code 옵셋 == 0x14를 찾아들어가니 다음과 같은 코드가 있습니다.

.method assembly hidebysig static void  ThreadStart_Context(object state) cil managed
{
  // Code size       60 (0x3c)
  .maxstack  2
  .locals init (class System.Threading.ThreadHelper V_0)
  IL_0000:  ldarg.0
  IL_0001:  castclass  System.Threading.ThreadHelper
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldfld      class System.Delegate System.Threading.ThreadHelper::_start
  IL_000d:  isinst     System.Threading.ThreadStart
  IL_0012:  brfalse.s  IL_0025
  IL_0014:  ldloc.0
  IL_0015:  ldfld      class System.Delegate System.Threading.ThreadHelper::_start
  IL_001a:  castclass  System.Threading.ThreadStart
  IL_001f:  callvirt   instance void System.Threading.ThreadStart::Invoke()
  IL_0024:  ret
  IL_0025:  ldloc.0
  IL_0026:  ldfld      class System.Delegate System.Threading.ThreadHelper::_start
  IL_002b:  castclass  System.Threading.ParameterizedThreadStart
  IL_0030:  ldloc.0
  IL_0031:  ldfld      object System.Threading.ThreadHelper::_startArg
  IL_0036:  callvirt   instance void System.Threading.ParameterizedThreadStart::Invoke(object)
  IL_003b:  ret
} // end of method ThreadHelper::ThreadStart_Context

이건 좀 의외군요. ldloc 코드에서 System.MissingMethodException 같은 예외가 발생한다는 것이 잘 납득이 되질 않습니다. 일단 "Watson Bucket" 분석은 이 정도로 끝내고.




이런 식으로 문제 재현이 되는 PC가 마음대로 접근할 수 있는 환경이라면, 당연히 Visual Studio의 강력한 디버깅 기능인 "원격 디버깅"을 사용해서 대부분의 문제를 해결할 수 있습니다.

문제는, 해당 ASP.NET 웹 애플리케이션이 실행되자마자 죽어버린다는 것입니다. "원격 디버깅"을 걸려면 "프로세스 목록"을 열람해야 하는데 그 작업을 들어갈 수가 없는 것입니다.

이런 경우에, ^^ 제가 주로 써 먹는 방법이 있는데요. 바로 ^^ ASP.NET이 올라오긴 전 상태로 w3wp.exe를 띄워놓기만 한 후 원격 디버거를 붙이는 것입니다. 다음과 같이 따라해주시면 어렵지 않게 할 수 있습니다.

  1. 만약 w3wp.exe가 실행중이라면 종료시키고,
  2. http://.../test.test와 같이 있지도 않은 페이지를 방문 시도.
  3. 그럼, w3wp.exe가 실행되는데 이 상태에서는 .NET이 올라와 있지 않게 됩니다.
  4. 이 시점에서 w3wp.exe 프로세스에 대해 Debugger를 attach 시켜 놓고. (BP 설정도 하고.)
  5. 정식으로 aspx 페이지를 방문하면, 그제서야 ASP.NET 관련 DLL들이 올라오면서 예외를 잡을 수 있습니다.

위와 같이 해서, 원격 디버깅 상태로 조사해 본 결과, 범인은 System.Threading.WaitHandle의 "public virtual bool WaitOne(int millisecondsTimeout);" 메서드였습니다.

missing_method_ex_clr2_1.png

도움말에서 찾아보니 "WaitOne(int millisecondsTimeout);" 메서드가 추가된 것은 2.0 SP2라고 되어 있는데 즉, 해당 사이트에서는 2.0 SP2 이후의 업데이트를 포함하고 있지 않아서 발생한 문제였습니다. (제품 개발을 하고 있는 제 PC를 포함해서 테스트 서버 4대 모두 윈도우 업데이트를 받고 있기 때문에 이런 문제가 미리 발견되지 못한 것이었습니다.)

휴~~~~ 솔루션 개발이란! ^^




여기서 한 가지 궁금한 사항이 있는데요. 아니... 그렇다면 Watson 버킷의 오류 보고 내용이 틀렸다는 것일까요?
결론적으로 틀렸다고는 말할 수 없지만, 어쨌든 직관적이지 않은 것만은 사실입니다.

해당 예외가 발생했을 때의 원격 디버깅 상에서의 콜스택을 보니 다음과 같았습니다.

at MyProduct.MyClass.MyFunc.Run()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

그러니까, Threadstart_Context를 실행하면서 WaitOne에 대한 함수를 찾을 수 없으니 그와 같은 예외가 발생한 것입니다.

문제가 되었던 코드로 돌아가 볼까요?

.method assembly hidebysig static void  ThreadStart_Context(object state) cil managed
{
  // Code size       60 (0x3c)
  .maxstack  2
  .locals init (class System.Threading.ThreadHelper V_0)
  IL_0000:  ldarg.0
  IL_0001:  castclass  System.Threading.ThreadHelper
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldfld      class System.Delegate System.Threading.ThreadHelper::_start
  IL_000d:  isinst     System.Threading.ThreadStart
  IL_0012:  brfalse.s  IL_0025
  IL_0014:  ldloc.0
  ...[생략]...
}

위에서 보면, "IL_0014" 옵셋에서 로드되는 인스턴스가 바로 사용자의 델리게이트 함수입니다. 즉, 사용자가 정의한 MyClass.MyFunc.Run 메서드가 적재되는 그 순간에 JIT 컴파일 과정이 이뤄지고 Run 메서드 내에 포함되어 있던 WaitOne 메서드를 찾을 수 없어 System.MissingMethodException 예외가 발생했던 것입니다.

어쨌든... 결국 System.MissingMethodException 같은 경우에는, 지난번 설명해 드렸던 것과는 달리 이벤트 로그의 정보만으로는 직접적인 문제 해결을 할 수 없다는 한계가 있다는 것을 알아둘 필요가 있겠습니다. (덤프를 떠서 windbg로 분석하면 나오겠군요.)

그나저나, 다중 CLR 버전을 지원하는 제품 개발에서는 System.MissingMethodException 예외를 아주 조심해야 할 것 같습니다. ^^

Method not found: 'Void System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[])'.
; https://www.sysnet.pe.kr/2/0/809



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

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/27/2021]

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

비밀번호

댓글 작성자
 




... 16  [17]  18  19  20  21  22  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
13223정성태1/20/20234740오류 유형: 838. RDP 연결 오류 - The two computers couldn't connect in the amount of time allotted
13222정성태1/20/20234414개발 환경 구성: 657. WSL - DockerDesktop.vhdx 파일 위치를 옮기는 방법
13221정성태1/19/20234606Linux: 57. C# - 리눅스 프로세스 메모리 정보파일 다운로드1
13220정성태1/19/20234704오류 유형: 837. NETSDK1045 The current .NET SDK does not support targeting .NET ...
13219정성태1/18/20234330Windows: 220. 네트워크의 인터넷 접속 가능 여부에 대한 판단 기준
13218정성태1/17/20234230VS.NET IDE: 178. Visual Studio 17.5 (Preview 2) - 포트 터널링을 이용한 웹 응용 프로그램의 외부 접근 허용
13217정성태1/13/20234833디버깅 기술: 185. windbg - 64비트 운영체제에서 작업 관리자로 뜬 32비트 프로세스의 덤프를 sos로 디버깅하는 방법
13216정성태1/12/20235070디버깅 기술: 184. windbg - 32비트 프로세스의 메모리 덤프인 경우 !peb 명령어로 나타나지 않는 환경 변수
13215정성태1/11/20236803Linux: 56. 리눅스 - /proc/pid/stat 정보를 이용해 프로세스의 CPU 사용량 구하는 방법 [1]
13214정성태1/10/20236135.NET Framework: 2087. .NET 6부터 SourceGenerator와 통합된 System.Text.Json [1]파일 다운로드1
13213정성태1/9/20235598오류 유형: 836. docker 이미지 빌드 시 "RUN apt install ..." 명령어가 실패하는 이유
13212정성태1/8/20235491기타: 85. 단정도/배정도 부동 소수점의 정밀도(Precision)에 따른 형변환 손실
13211정성태1/6/20235432웹: 42. (https가 아닌) http 다운로드를 막는 웹 브라우저
13210정성태1/5/20234581Windows: 219. 윈도우 x64의 경우 0x00000000`7ffe0000 아래의 주소는 왜 사용하지 않을까요?
13209정성태1/4/20234476Windows: 218. 왜 윈도우에서 가상 메모리 공간은 64KB 정렬이 된 걸까요?
13208정성태1/3/20234441.NET Framework: 2086. C# - Windows 운영체제의 2MB Large 페이지 크기 할당 방법파일 다운로드1
13207정성태12/26/20224720.NET Framework: 2085. C# - gpedit.msc의 "User Rights Assignment" 특권을 코드로 설정/해제하는 방법파일 다운로드1
13206정성태12/24/20224984.NET Framework: 2084. C# - GetTokenInformation으로 사용자 SID(Security identifiers) 구하는 방법 [3]파일 다운로드1
13205정성태12/24/20225222.NET Framework: 2083. C# - C++과의 연동을 위한 구조체의 fixed 배열 필드 사용 (2)파일 다운로드1
13204정성태12/22/20224660.NET Framework: 2082. C# - (LSA_UNICODE_STRING 예제로) CustomMarshaler 사용법파일 다운로드1
13203정성태12/22/20224816.NET Framework: 2081. C# Interop 예제 - (LSA_UNICODE_STRING 예제로) 구조체를 C++에 전달하는 방법파일 다운로드1
13202정성태12/21/20225194기타: 84. 직렬화로 설명하는 Little/Big Endian파일 다운로드1
13201정성태12/20/20225753오류 유형: 835. PyCharm 사용 시 C 드라이브 용량 부족
13200정성태12/19/20224704오류 유형: 834. 이벤트 로그 - SSL Certificate Settings created by an admin process for endpoint
13199정성태12/19/20224893개발 환경 구성: 656. Internal Network 유형의 스위치로 공유한 Hyper-V의 VM과 호스트가 통신이 안 되는 경우
13198정성태12/18/20224816.NET Framework: 2080. C# - Microsoft.XmlSerializer.Generator 처리 없이 XmlSerializer 생성자를 예외 없이 사용하고 싶다면?파일 다운로드1
... 16  [17]  18  19  20  21  22  23  24  25  26  27  28  29  30  ...