Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 11개 있습니다.)
디버깅 기술: 6. .NET 예외 처리 정리
; https://www.sysnet.pe.kr/2/0/316

디버깅 기술: 15. First-Chance Exception
; https://www.sysnet.pe.kr/2/0/510

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

.NET Framework: 110. WPF - 전역 예외 처리
; https://www.sysnet.pe.kr/2/0/614

디버깅 기술: 42. Watson Bucket 정보를 이용한 CLR 응용 프로그램 예외 분석 - (2)
; https://www.sysnet.pe.kr/2/0/1096

.NET Framework: 534. ASP.NET 응용 프로그램이 예외로 프로세스가 종료된다면?
; https://www.sysnet.pe.kr/2/0/10863

.NET Framework: 538. Thread.Abort로 인해 프로세스가 종료되는 현상
; https://www.sysnet.pe.kr/2/0/10867

디버깅 기술: 110. 비동기 코드 실행 중 예외로 인한 ASP.NET 프로세스 비정상 종료 현상
; https://www.sysnet.pe.kr/2/0/11383

디버깅 기술: 119. windbg 분석 사례 - 종료자(Finalizer)에서 예외가 발생한 경우 비정상 종료(Crash) 발생
; https://www.sysnet.pe.kr/2/0/11732

닷넷: 2148. C# - async 유무에 따른 awaitable 메서드의 병렬 및 예외 처리
; https://www.sysnet.pe.kr/2/0/13422

닷넷: 2213. ASP.NET/Core 웹 응용 프로그램 - 2차 스레드의 예외로 인한 비정상 종료
; https://www.sysnet.pe.kr/2/0/13551




비동기 코드 실행 중 예외로 인한 ASP.NET 프로세스 비정상 종료 현상

따끈따끈한 글이 하나 올라왔군요. ^^

Using WinDbg to Analyze .NET Crash Dumps - Async Crash
; https://stackify.com/using-windbg-to-analyze-net-crash-dumps-async-crash/

그러니까, 결국 위의 글은 async/await 동작에서 예외가 발생했는데 w3wp.exe가 비정상 종료한다는 것입니다. 재현을 한번 해볼까요? 간단하게 Visual Studio에서 MVC 웹 애플리케이션을 기본 설정으로 만든 후, HomeController.cs 파일의 About에 다음과 같이 async/await를 구현해 봅니다.

public async Task<ActionResult> About()
{
    ViewBag.Message = "Your application description page.";

    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage hrm = await client.GetAsync("http://www.naver.com");
        string txt = hrm.Content.ToString();
        string txt2 = txt.Substring(0, 32767 * 1024);
    }

    return View();
}

위의 코드는 분명히 예외를 발생시키지만, 프로세스 종료로 이어지지는 않습니다. 제 기억이 맞는지는 모르겠지만, 초기 async/await 구현 시에는 위의 상황에서도 비정상 종료가 되는 문제가 있었습니다. 왜냐하면 다음의 규칙 때문입니다.

ASP.NET 응용 프로그램이 예외로 프로세스가 종료된다면?
; https://www.sysnet.pe.kr/2/0/10863

이후, 적절한 SynchronizationContext와 연결된 비동기 호출인 경우 예외가 발생하더라도 비정상 종료(crash)까지는 하지 않도록 바뀌었습니다.

하지만 여전히 SynchronizationContext가 없는 2차 스레드에서의 예외에 대해서는 비정상 종료가 발생합니다. 가령 다음과 같이 호출하면 비정상 종료합니다.

public ActionResult About()
{
    ViewBag.Message = "Your application description page.";

    Thread t1 = new Thread(testFunc);
    t1.IsBackground = true;
    t1.Start();

    return View();
}

async void testFunc()
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage hrm = await client.GetAsync("http://www.naver.com");
        string txt = hrm.Content.ToString();
        string txt2 = txt.Substring(0, 32767 * 1024);
    }
}

하지만 엄밀히 말해서 위의 코드는 await 비동기 호출에서 예외가 발생했기 때문에 crash가 되는 것은 아닙니다. 즉, testFunc 자체가 2차 스레드이기 때문에 그 안에서는 await 호출이 없어도 예외가 발생하면 비정상 종료가 되는 것입니다. 그러니까 따지고 보면 "Using WinDbg to Analyze .NET Crash Dumps - Async Crash" 글은 비동기이기 때문에 발생한 상황은 아닌 것입니다.

2차 스레드에서의 (비동기 호출을 포함해) 예외가 발생해도 비정상 종료하지 않게 만들려면 "ASP.NET 응용 프로그램이 예외로 프로세스가 종료된다면?" 글에서도 소개했던 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" />
        <shadowCopyVerifyByTimestamp enabled="true"/>
    </runtime>
    <startup useLegacyV2RuntimeActivationPolicy="true" />
</configuration>

그런데... 설정하기 전에 그 차이점을 확실하게 알고 하는 것이 좋습니다.

만약, legacyUnhandledExceptionPolicy 값을 true로 설정한다면? 비정상 종료는 하지 않겠지만 예외가 발생했다는 것을 모르고 지나갈 수 있습니다. 가령 "Using WinDbg to Analyze .NET Crash Dumps - Async Crash" 글에서도 비정상 종료 현상이 없었다면 아마도 그 고객사는 한참 동안 해당 문제가 발생하고 있는지도 모른 체로 서비스를 계속했을 것입니다.

반면, legacyUnhandledExceptionPolicy 값을 false로 설정한다면? 당장 비정상 종료 현상은 겪겠지만 문제 발생 여부를 바로 알 수 있어 발 빠르게 대응을 할 수 있습니다.

여러분은 어떤 것을 서비스의 기본 값으로 설정하시겠습니까? ^^




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 9/18/2019]

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

비밀번호

댓글 작성자
 



2018-04-23 11시47분
정성태

1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13460정성태11/26/20232371닷넷: 2172. .NET 6+ 기반의 COM Server 내에 Type Library를 내장하는 방법파일 다운로드1
13459정성태11/26/20232370닷넷: 2171. .NET Core 3/5+ 기반의 COM Server를 기존의 regasm처럼 등록하는 방법파일 다운로드1
13458정성태11/26/20232377닷넷: 2170. .NET Core/5+ 기반의 COM Server를 tlb 파일을 생성하는 방법(tlbexp)
13457정성태11/25/20232301VS.NET IDE: 187. Visual Studio - 16.9 버전부터 추가된 "Display inline type hints" 옵션
13456정성태11/25/20232627닷넷: 2169. C# - OpenAI를 사용해 PDF 데이터를 대상으로 OpenAI 챗봇 작성 [1]파일 다운로드1
13455정성태11/25/20232518닷넷: 2168. C# - Azure.AI.OpenAI 패키지로 OpenAI 사용파일 다운로드1
13454정성태11/23/20232861닷넷: 2167. C# - Qdrant Vector DB를 이용한 Embedding 벡터 값 보관/조회 (Azure OpenAI) [1]파일 다운로드1
13453정성태11/23/20232345오류 유형: 879. docker desktop 설치 시 "Invalid JSON string. (Exception from HRESULT: 0x83750007)"
13452정성태11/22/20232450닷넷: 2166. C# - Azure OpenAI API를 이용해 사용자가 제공하는 정보를 대상으로 검색하는 방법파일 다운로드1
13451정성태11/21/20232582닷넷: 2165. C# - Azure OpenAI API를 이용해 ChatGPT처럼 동작하는 콘솔 응용 프로그램 제작파일 다운로드1
13450정성태11/21/20232387닷넷: 2164. C# - Octokit을 이용한 GitHub Issue 검색파일 다운로드1
13449정성태11/21/20232493개발 환경 구성: 688. Azure OpenAI 서비스 신청 방법
13448정성태11/20/20232793닷넷: 2163. .NET 8 - Dynamic PGO를 결합한 성능 향상파일 다운로드1
13447정성태11/16/20232675닷넷: 2162. ASP.NET Core 웹 사이트의 SSL 설정을 코드로 하는 방법
13446정성태11/16/20232636닷넷: 2161. .NET Conf 2023 - Day 1 Blazor 개요 정리
13445정성태11/15/20232933Linux: 62. 리눅스/WSL에서 CA 인증서를 저장하는 방법
13444정성태11/15/20232678닷넷: 2160. C# 12 - Experimental 특성 지원
13443정성태11/14/20232736개발 환경 구성: 687. OpenSSL로 생성한 사용자 인증서를 ASP.NET Core 웹 사이트에 적용하는 방법
13442정성태11/13/20232526개발 환경 구성: 686. 비주얼 스튜디오로 실행한 ASP.NET Core 사이트를 WSL 2 인스턴스에서 https로 접속하는 방법
13441정성태11/12/20232836닷넷: 2159. C# - ASP.NET Core 프로젝트에서 서버 Socket을 직접 생성하는 방법파일 다운로드1
13440정성태11/11/20232460Windows: 253. 소켓 Listen 시 방화벽의 Public/Private 제어 기능이 비활성화된 경우
13439정성태11/10/20233056닷넷: 2158. C# - 소켓 포트를 미리 시스템에 등록/예약해 사용하는 방법(Port Exclusion Ranges)파일 다운로드1
13438정성태11/9/20232625닷넷: 2157. C# - WinRT 기능을 이용해 윈도우에서 실행 중인 Media App 제어
13437정성태11/8/20232792닷넷: 2156. .NET 7 이상의 콘솔 프로그램을 (dockerfile 없이) 로컬 docker에 배포하는 방법
13436정성태11/7/20233015닷넷: 2155. C# - .NET 8 런타임부터 (Reflection 없이) 특성을 이용해 public이 아닌 멤버 호출 가능
13435정성태11/6/20232936닷넷: 2154. C# - 네이티브 자원을 포함한 관리 개체(예: 스레드)의 GC 정리
1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...