We saw similar behavior for a while, and it turned out to be a subtle bug in our 
shutdown code. 
Our logic went:
1 - Receive BeginReceive callback (call EndReceive)
2 - Check for zero bytes - (socket shutdown)
3 - Perform work on data that was received
4 - Check to see if Socket is Shutdown
4 - Call BeginReceive
 
The bug here (at least in the way we implemented it) is that while we were doing work, 
it's possible for the socket to be shutdown. When this happens, we wouldn't get the 
callback, and the socket would be orphaned, and we would leak memory. 
 
The thing that made this so irritating was the need to use .NET Exceptions for program 
flow control. Calling BeginReceive on a socket that has been shutdown results in an 
error - but testing to see if the socket is shutdown prior to calling BeginReceive 
results in a (small) race condition that our stress tests were repeadily able to hit. 
 
We fixed this in two ways:
1 - Much Cleaner shutdown logic
2 - On app startup allocate a big pool of 1K Buffers, and all them to be "checked in" 
or "checked out" when sockets are created and destroyed. This kept the Managed Heap 
from becoming badly fragmented, as all of the buffers are right next to each other in 
memory, thereby avoiding holes. The pool of buffers grows in size as needed by 
allocate "alot" of buffers at a time. 
 
We have stress tested the living daylights out of our server, and are very confident 
we're not leaking sockets and/or memory. The .NET socket code has been amazingly 
reliable. 
 
-- 
Chris Mullins
 
----- Original Message -----
From: "Garry Barclay" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, July 21, 2004 1:09 PM
Subject: [ADVANCED-DOTNET] Missing callbacks from asynchronous sockets?


> It appears that we are NOT receiving the (completion port) callback from
> an asynchronous socket (BeginSend/EndSend) call.
>
> The sockets are clients and the failure seems to be related to shutdowns
> on the socket.
>
> This has the effect of leaving a pinned GCHandle on the heap (pinning the
> send buffer). We've checked the process memory dump with WinDbg and have
> seen that the sockets are shutdown successfully. Checking the Socket class
> implementation (v1.1) with Reflector it's seems clear that IF the callback
> is made then the buffer should always be unpinned.
>
> We've added in static counters using interlocked.xxx to verify that the
> calls are definitely not reaching our code, and this confirms our
> suspicions.
>
> Because of the pinned buffers, heap compaction can't take place and we end
> up with high memory usage figures even though most of the heap is free
> space between those buffers.
>
> Anyone seen something like this before?
>
> ===================================
> This list is hosted by DevelopMentor  http://www.develop.com
> Some .NET courses you may be interested in:
>
> NEW! Guerrilla ASP.NET, 17 May 2004, in Los Angeles
> http://www.develop.com/courses/gaspdotnetls
>
> View archives and manage your subscription(s) at
http://discuss.develop.com

===================================
This list is hosted by DevelopMentor  http://www.develop.com
Some .NET courses you may be interested in:

NEW! Guerrilla ASP.NET, 17 May 2004, in Los Angeles
http://www.develop.com/courses/gaspdotnetls

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to