Microsoft MVP성태의 닷넷 이야기
Socket 관련 Leak (OverlappedAsyncResult, OverlappedData) 관련 문의 [링크 복사], [링크+제목 복사],
조회: 11511
글쓴 사람
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분
아쉬운 결과군요. 그래도 어쨌든 제품을 안정적으로 만드셨으니 다행입니다. ^^
정성태

... 61  62  63  64  65  66  67  68  69  [70]  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
818개발돌이8/14/200917245ActiveX개발한 dll을 임베디드 할때 UI에 대한 질문 [1]파일 다운로드1
817채승수8/13/200916551클릭원스 관련 질문드립니다.~ [1]
816박진오7/29/200915861다국어 사이트의 컨텐츠 저장 방식에 대해.. [2]
814서광원7/16/200924766IWebBrowser2를 이용한 프로그램에서 javascript의 alert 창 무시하는 법? [1]
813윤상균7/16/200915656비관리코드와의 상호운용에서 마샬링 질문 [1]
812김현우7/13/200916142usercontrol은 mdi container가 될수 없는데 이를 구현할 방법은 무엇일런지요? [2]
811조민수7/3/200915599MSDN Magazine 한글화 않되나요? [1]
810세경6/29/200921036SmartClient Vista 64bit IE7 [4]
809윤석준6/24/200921006IE -nomerge 옵션으로 새창을 열려고 합니다. [1]
808한승훈6/4/200919807dll import하기 위해 struct 구성시에 struct가 struct를 가지고 있고 포함된 struct가 ByValArray형태일때 해결 [1]
806곰티5/26/200917931defcon pro 설치 원천 봉쇄 방법 문의 [3]
802채승수5/8/200917009신뢰사이트 등록/적용에 관해 질문드립니다. [1]
801채승수4/15/200917887IE8 새세션을 코드로 구현할수 없을까요 [1]
800신동열4/7/200918061IE8에서 스마트 클라이언트 로딩 문제 [2]
7993/27/200921798이벤트 로그 오류 [1]
798천해3/26/200918335IE8.0 에 관해 질문 드립니다. [2]
797궁금..3/23/200918259IE 8 관련 질문.. [2]
796정성태3/20/200916833스마트클라이언트와 ActiveX에 관한 질문 [1]
795김기용3/19/200916498[질문] DHTML 다이얼로그 관련 [2]
794박평옥3/18/200916833Vista에서 URL Shortcut 실행 시 SetSite가 두 번 호출되는 증상에 관해 조언 부탁드립니다. [2]
792김기용3/12/200915975어제 세미나 잘 들었습니다. 질문사항이 있습니다.(ie8 마이그레이션 관련) [4]
791vb표성백2/17/200921458ATL 로 만든 COM 에 문자열 전달하기! C#에서 어떻게 하나요? [1]
790고민중2/16/200914076vista에 vs2005를 사용중입니다. [1]
789지언2/14/200916132MFC & C#(COM) 호환 관련하여 답변좀 부탁드립니다 [2]
788하루야채2/3/200915124스마트클라이언트 Windowless 설정에 대해서 문의드립니다. [2]
787궁금이2/2/200915578TFS 관련하여 질문드리고자 합니다. [2]
... 61  62  63  64  65  66  67  68  69  [70]  71  72  73  74  75  ...