[출처] System.Runtime.InteropServices.SEHException - 0x80004005|작성자 techshare
SEHException은 "unmanaged code" 영역에서 발생한 것으로 .NET 예외에는 매핑이 되지 않아 필요한 문맥 정보가 그다지 많지 않습니다.
(여러 가지 발생 상황이 있겠지만) 간단한 예로 다음의 코드로 재현하는 것이 가능합니다.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
static void Main(string[] args)
{
int pid = Process.GetCurrentProcess().Id;
while (true)
{
try
{
Process proc = Process.GetProcessById(pid);
Console.Write(".");
CloseHandle(proc.Handle); // 핸들을 닫음
} catch { }
// GC.Collect(2, GCCollectionMode.Forced);
Thread.Sleep(1000);
}
}
}
}
위의 코드를 F5 디버그 모드로 실행하면 어느 순간 다음과 같은 예외가 발생합니다. (또는, 위의 코드에서 주석 처리한 GC.Collect를 해제하면 곧바로 발생합니다.)
System.Runtime.InteropServices.SEHException occurred HResult=0x80004005 Message=External component has thrown an exception. Source=<Cannot evaluate the exception source> StackTrace: <Cannot evaluate the exception stack trace> - $exception {"External component has thrown an exception."} System.Runtime.InteropServices.SEHException + Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} ErrorCode -2147467259 int HResult -2147467259 int HelpLink null string + IPForWatsonBuckets 0x0000000000000000 System.UIntPtr + InnerException null System.Exception IsTransient false bool Message "External component has thrown an exception." string RemoteStackTrace null string Source "System" string StackTrace " at Microsoft.Win32.SafeNativeMethods.CloseHandle(IntPtr handle)\r\n at Microsoft.Win32.SafeHandles.SafeProcessHandle.ReleaseHandle()\r\n at System.Runtime.InteropServices.SafeHandle.InternalFinalize()\r\n at System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)\r\n at System.Runtime.InteropServices.SafeHandle.Finalize()" string + TargetSite {Boolean CloseHandle(IntPtr)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo} + WatsonBuckets {byte[5616]} object {byte[]} _HResult -2147467259 int _className "System.Runtime.InteropServices.SEHException" string + _data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} _dynamicMethods null object + _exceptionMethod {Boolean CloseHandle(IntPtr)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo} _exceptionMethodString null string _helpURL null string + _innerException null System.Exception + _ipForWatsonBuckets 0x0000000000000000 System.UIntPtr _message "External component has thrown an exception." string _remoteStackIndex 0 int _remoteStackTraceString null string + _safeSerializationManager {System.Runtime.Serialization.SafeSerializationManager} System.Runtime.Serialization.SafeSerializationManager _source "System" string + _stackTrace {sbyte[192]} object {sbyte[]} _stackTraceString null string + _watsonBuckets {byte[5616]} object {byte[]} _xcode -532462766 int + _xptrs 0x0000000000000000 System.IntPtr + Static members
GC가 수행된 후 연결되는 Finalizer 실행에 의해 발생하는 것이므로 일반적인 call stack 정보를 알아낼 수는 없습니다. 게다가 Finalizer의 수행 시점이 불확실하기 때문에 실제 운영 상황에서는 프로세스가 어느 순간 아무 이유 없이 종료하는 현상처럼 보이게 됩니다.
다행히, 이번처럼 간단한 예제의 경우에는 콜 스택을 통해 Handle 관리가 잘못되었다는 것을 짐작할 수 있으므로 CloseHandle(proc.Handle) 코드를 삭제하는 것으로 해결할 수 있지만, 운이 나쁘면 디버깅에 장난 아닌 시간을 들여야 할지도 모릅니다.
참고로, 위의 코드를 디버거 없이 단독 실행하는 경우에는 SEHException 예외가 발생하지 않습니다. 이걸 다행이라고 해야 할지는 모르겠군요. ^^