Microsoft MVP성태의 닷넷 이야기
Socket 관련 Leak (OverlappedAsyncResult, OverlappedData) 관련 문의 [링크 복사], [링크+제목 복사],
조회: 11527
글쓴 사람
Syong (ianstory01 at naver.com)
홈페이지
첨부 파일

안녕하세요. .netFramework 4.5 사용 중인데, 최근 소켓 관련해서 해결하지 못하고 있는 문제가
있어 도움을 받고자 문의드립니다.

여러 대의 PC에서 동일한 프로그램으로 장비를 운영 중인데,
며칠이 지나서 보면 불규칙하게 메모리가 증가해있더라구요.
현장에서 메모리 분석을 할 수 없어 노트북으로 재현을 해봐도 나오지 않았는데,
오늘 우연히 딱 한 번 어떤 이유에서인지 재현이 되어 메모리를 확인할 수 있었는데,
OverlappedAsyncResult, OverlappedData 이 쪽에서 메모리가 급증해있더라구요.
조금 찾아보니 제가 Socket을 Async로 연결, 송수신을 처리했었는데,
구글링을 해보니 관련 이슈가 있는 건 알겠는데 명확히 해결 된 사례를 보지 못해서요ㅠ
연결, 메시지 송수신에 관련된 부분에 관한 소스를 첨부합니다.
Leak이라면, 일정 시간, 일정 주기로 항상 재현이 되야할 것 같은데...
그렇지 않아 어렵네요 ㅠ








[최초 등록일: ]
[최종 수정일: 2/14/2023]


비밀번호

댓글 작성자
 



2023-02-15 08시34분
제시하신 소켓 소스 코드로 재현 상황을 만들어 보세요. 운영 중인 것과 몇 배속으로 dummy 데이터 입/출력을 해보시고, 재현이 되면 그 프로젝트를 올려주세요.

재현이 안 되면, 가정만 하게 되고 그걸로 핑퐁하다 보면 시간만 갈 뿐입니다. 일례로... "EndReceive/EndSend 시에 예외가 발생할 수 있을 텐데, 그때 왜 소켓을 닫지 않는 거죠?"라고 말한 다음... ^^ 응답을 기다리다 그건 이러저러해서 처리가 되었다고 하면 또 다른 가정을 하게 될 것입니다.

(참고로, 운영에서 재현이 잘 된다면 고객 측에 양해를 구하고 잠깐 메모리 덤프를 떠서 사후 분석해 보는 것은 어떨까요?!!)
정성태
2023-02-21 07시33분
[Syong] 재현도 너무 불규칙하게 되는지라... 발생 조건을 아직 명확히 몰라서요...
메모리 프로파일러는 돌려봤는데.. 혹시 System.Threading.PinnableBufferCache가 쌓이는 것 같은데,
(ConcurrentStack<T>+Node<object>가 증가해서 내용을 봤더니 PinnableBufferCache) 가 있더라구요.
혹시 이게 뭘까요??ㅠ
[guest]
2023-02-21 08시24분
아래의 글로 정리했으니 한번 참고하세요.

C# - 비동기 소켓 사용 시 메모리 해제가 finalizer 단계에서 발생하는 사례
; https://www.sysnet.pe.kr/2/0/13267

그나저나, 해당 메모리가 끝없이 늘고 있나요? 아니면 어느 정도만 늘고 있나요? 만약 전자의 경우라면 Socket.Close만 제대로 해줘도 그런 현상이 사라질 것입니다. 반면, 후자의 경우라면 어떤 식으로든 해당 개체의 참조를 유지하고 있는 측이 있으므로 그것을 찾아 해결을 하셔야 합니다.
정성태
2023-02-23 01시41분
[Syong] 답변 글 확인했습니다! 자세한 답변 감사합니다.
이번 문제 관련해서 로그 분석 과정에서 새롭게 확인된 내용이 있어 테스트 결과 재현이 되었는데요,
메모리가 증가하는 시점부터 SendCallback 함수에 넣어둔 Send에 관한 로그가 찍히지 않아 확인해보니,
Callback 함수로 들어오지 않고 있더라구요(50ms 간격으로 두 프로그램 간 계속 통신해야하는데, 설비마다 각기 다른 시간(1~4일)이 지나고 지난 후). 그래서 테스트 프로그램으로 대용량 메시지를 만들어서 BeginSend로 메시지를 전달해보니 실제로 메시지가 전달되지도 않고, Callback 함수도 타지 않으며 메모리 누수가 발생하더라구요.
다른 방법으로 Send는 비동기로 하지않고, 동기로 하고 같은 대용량 메시지를 전달해도 메시지가 잘 전달되고, 누수도 발생하지 않았습니다. BeginSend와 Callback 처리에서 메모리가 누수되고 있는데, 이에 대해 처리해줘야하는 내용이 있을까요?
한가지 더 질문은 Send를 비동기로 처리했던 이유는 Callback 함수로 들어왔다면 확실히 전송되었다고 판단하고 로그를 찍기 위함이었습니다.
[guest]
2023-02-23 02시28분
대용량으로 보냈을 때 SendCallback이 호출되지 않는 것은 상황에 따라 그럴 수 있습니다.

Socket의 Send 동작은 SendBufferSize 크기의 메모리가 여유가 있을 때입니다. 쉽게 예를 들어 SendBufferSize가 4KB이고 그렇게 정해진 버퍼에 현재 전송되지 않은 데이터가 2KB가 쌓여 있는 중에 뒤이어 send(4KB)가 들어오면 SendBuffer가 담을 수 없으므로 blocking이 생깁니다.

위의 시나리오를 비동기로 따져보면, async_send(4KB)를 한 경우 전송 버퍼에 담지 못했으므로 SendCallback이 발생하지 않습니다. 그러면서 전달된 4KB는 메모리에 있게 되는데요, 그런 식으로 대용량 send가 발생하면 마치 메모리 릭이 발생하는 것처럼 보이는 것뿐입니다.

여기서 문제는 "receive를 하는 Socket Server"가 될 수 있습니다. 서버 측에서 Receive를 하지 않아 TCP 입력 버퍼가 비어 있지 않게 되고 (또는, 클라이언트 측에서 전송하는 데이터에 비해 느리게 비우면), 그럼 send한 측에서는 SendBufferSize만큼 누적되다가 이후에는 메모리에 쌓이게 되는 것입니다.

------------------

일단 원칙은 그렇고요, Syong 님의 덧글에 따르면 비동기로 한 경우에는 SendCallback이 안 찍히고, 동기 send한 경우에는 모든 것이 정상적으로 돌아갔다는 건데요... 음... ^^; 이론상 이것은 맞지 않는 동작입니다. 2가지 경우 모두 서버에서 receive를 해주고 있는 상황이라면 모두 정상적으로 동작해야 합니다. (혹시 간단하게 재현되는 예제가 있으면 첨부해주세요.)

이 부분에 대해 설명할 수 있는 차이점을 발견하셔야 합니다. ^^;

------------------

두 번째 질문은 위에서 설명한 것과 이어지는데요, (동기든 비동기든) send가 된 것은 SendBuffer에 추가되었을 때 반환(또는 callback)이 됩니다. 그러니까, 그게 확실히 전송된 것과는 무관합니다. 왜냐하면 send buffer에 쌓인 후, 서버 측에서 receive를 하지 않았거나, 아니면 그 사이에 네트워크가 끊기면 그냥 그걸로 끝입니다. (TCP의 안정성은, 양 끝단이 살아 있을 때 버퍼의 내용을 모두 보내준다는 것을 보증하는 정도입니다.)

"확실"한 것을 어느 수준으로 정해야 하는 문제가 있는데요, 만약 "확실함"의 기준이 send 후 서버에서 해당 패킷이 처리되었다는 지점까지 원한다면 callback만으로는 부족합니다.

관련해서는 다음의 글도 한번 읽어보세요.

Wireshark + C#으로 확인하는 ReceiveBufferSize(SO_RCVBUF), SendBufferSize(SO_SNDBUF)
; https://www.sysnet.pe.kr/2/0/12532
정성태
2023-03-20 04시40분
[Syong] 결국은 일정하게 재현도 안되고, 24시간 운영하는 설비들에서 불규칙하게 1~5일이 지나면 동일 증상이 발생해서...
C++로 Winsock core만 작성해서 C++/CLI로 랩핑한 걸 C#에서 사용하는 방안으로 해결 아닌 해결을 해서 운영하고 있네요 ㅠ
[guest]
2023-03-20 06시15분
아쉬운 결과군요. 그래도 어쨌든 제품을 안정적으로 만드셨으니 다행입니다. ^^
정성태

... 76  77  78  79  80  81  82  83  84  [85]  86  87  88  89  90  ...
NoWriterDateCnt.TitleFile(s)
353정성태4/20/200617909    답변글 [답변]: 이번겨울방학때세도나를 여행하려구하는데요,,,
351오기4/18/200610711aspx [2]
350유지연4/17/200611461smartclient DB connection관련 질문 입니다. [2]파일 다운로드1
349선재빠4/17/200611464object tag를 2개 넣으면 IE가 죽어버리네요. [2]
347박찬용4/13/200611485COM+에 관한 질문입니다. [2]
345선재빠4/11/200612298Winform을 띄울 수 있는 방법이 있나요? [3]
344선재빠4/10/200613552ASP.NET 2.0에서는 VIEWASTEXT 이란 태그옵션을 지원하지 않는군요 [3]
343선재빠4/10/200612661아래와 같은 에러가 나네요.
341선재빠4/8/200612357테스트 페이지를 보면 프레임만 나오고 안에 내용이 나오지 않는군요 [1]
340김형태4/4/200611521파일서버 관련 질문드립니다.. (데브피아 답변에 이어) [2]
339조남정4/4/200611687post 주소 읽어오기 [1]
338장두헌4/4/200613290SDK PlatForm 다시 질문 - 데브피아의 내용 [1]
337강완모4/3/200613573Cab파일이 아닌 설치용 파일로 OCX들 설치하기... [1]
335비니3/23/200614513밑에 Smart Client에 대해서 질문했던 초보입니다.. TreeView컨트롤은 보이는데 안에 내용이 안보여요. [1]
336비니3/24/200612431    답변글 [재질문]:자꾸 죄송합니다...링크페이지로 이동을 안해요.... [1]
334비니3/23/200612130Smart Client강의 따라해보다가 xml에서 활성스키마는 <Tree>,<L> 요소는 지원하지 않는다고 나와요.ㅠㅠ [1]
332정준명3/21/200612180[자문자답] VS.NET에서 COM을 참조했는데, 강력한 서명이 없다고 사용불가네요.
333정성태3/22/200610707    답변글 [답변]: [자문자답] VS.NET에서 COM을 참조했는데, 강력한 서명이 없다고 사용불가네요. [1]
330심현철3/3/200613831[질문] VS2005에서 C#으로 개발한 DLL을 Javascript에서 접근할 수 없습니다. (ActiveX with C#) [2]
329권인성2/27/200612016스마트클라이언트(clickonce) 버전관리 [1]
327권인성2/24/200611636clickonce를 통해 설치 및 업데이트하려고 하는데요...보안때문에요..
331정성태3/12/200612709    답변글 [답변]: clickonce를 통해 설치 및 업데이트하려고 하는데요...보안때문에요..
325권인성2/23/200611219SETUP 및 배포관련 [1]
326권인성2/23/200610703    답변글 [답변]: 한가지만 더 질문할게요.... [1]
323정보문2/21/200611039메일 내용에서 한글이 깨집니다. [1]파일 다운로드1
321셈토2/18/200610855SPOOL --> EMF --> TEXTOUT [1]
... 76  77  78  79  80  81  82  83  84  [85]  86  87  88  89  90  ...