473,400 Members | 2,163 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,400 software developers and data experts.

Socket Async Send I/O - Resource Leak / Callbacks not getting called?

Greetings all.

Here's a problem that's been driving me nuts for the last 48 hours.
I'm hoping that someone has come across this before.

I have a C# Application that reads a UDP broadcast (asynchronously).
Then it repackages these UDP packets and sends them to a subscriber
via TCP.

Now, I can read the UDP stream all day long without the application
ever using more memory. Everything get's GC'ed just fine.

If I connect a subscriber, and start dispatching the incoming packets
via BeginSend() everything goes according to plan.. for a short while.
Suddenly the application memory consumption starts increasing... and
I've profiled the memory with ".NET Memory Profiler".
It seems that there are many instances of something called
"OverlappedData" accumulating, which I think they mean to be:
"NativeOverlapped".
These are created, but never collected by the GC.

Yes.. I am calling "EndSend()" on the callback from "BeginSend()" in
case you are wondering.
But here's the thing... I've implemented a counter that increments
each BeginSend() dispatch and one counter that increments each
EndSend() callback. After a while I start seeing small differences
that do not go away after the GC kicks in, indicating that a few
Begins were naughty and didn't call back!!

I've googled everywhere and chased up any reference on resource leaks
in Async I/O under .NET but found nothing that indicated that
callbacks might get lost.

I'm at the end of my wits here. Hualp!! Has anyone ever encountered
something similar?

Many thanks in advance,

Dennis Richardson

PS: I've tried this under Windows Vista (64-bit) & Windows XP (32-
bit), no change whatsoever. I'm sure I'm doing something wrong... but
what?

Apr 25 '07 #1
15 8348
Can you post a "short but complete" block of working sample code to
illustrate what you are doing that's causing the issue?
Peter

--
Site: http://www.eggheadcafe.com
UnBlog: http://petesbloggerama.blogspot.com
Short urls & more: http://ittyurl.net


"de***************@gmx.net" wrote:
Greetings all.

Here's a problem that's been driving me nuts for the last 48 hours.
I'm hoping that someone has come across this before.

I have a C# Application that reads a UDP broadcast (asynchronously).
Then it repackages these UDP packets and sends them to a subscriber
via TCP.

Now, I can read the UDP stream all day long without the application
ever using more memory. Everything get's GC'ed just fine.

If I connect a subscriber, and start dispatching the incoming packets
via BeginSend() everything goes according to plan.. for a short while.
Suddenly the application memory consumption starts increasing... and
I've profiled the memory with ".NET Memory Profiler".
It seems that there are many instances of something called
"OverlappedData" accumulating, which I think they mean to be:
"NativeOverlapped".
These are created, but never collected by the GC.

Yes.. I am calling "EndSend()" on the callback from "BeginSend()" in
case you are wondering.
But here's the thing... I've implemented a counter that increments
each BeginSend() dispatch and one counter that increments each
EndSend() callback. After a while I start seeing small differences
that do not go away after the GC kicks in, indicating that a few
Begins were naughty and didn't call back!!

I've googled everywhere and chased up any reference on resource leaks
in Async I/O under .NET but found nothing that indicated that
callbacks might get lost.

I'm at the end of my wits here. Hualp!! Has anyone ever encountered
something similar?

Many thanks in advance,

Dennis Richardson

PS: I've tried this under Windows Vista (64-bit) & Windows XP (32-
bit), no change whatsoever. I'm sure I'm doing something wrong... but
what?

Apr 25 '07 #2
Hi Dennis,
I'm at the end of my wits here. Hualp!! Has anyone ever encountered
something similar?
yes, quite similar.
But here's the thing... I've implemented a counter that increments
each BeginSend() dispatch and one counter that increments each
EndSend() callback. After a while I start seeing small differences
that do not go away after the GC kicks in, indicating that a few
Begins were naughty and didn't call back!!
Do you experience data loss like packets sent, but never received by the
client?
Do you pass an 'out Error' object to BeginSend()? It would not change the
outcome, but could provide a clue.

My server applications get data over UDP, process it and pass processed
data to clients via TCP, same thing as you do. The memory use creeps up
until it reaches a certain limit, then GC 'wakes up' and reduces the amount
of memory for application use about 2.5 - 3 times and from that moment kept
at lower level then at program start. It may take a week before it happens.
I was quite nervous about this. My server applications run unattended for
several month. Since they never crash I am more confident by now. Still, I
have serious reservations about Asynchronous Sockets implementation under
..NET 2.0. A call back never called is just half of the potential problem.
The other half is when the call back is called but the result of Endxxx() is
a disposed object. I never experienced it with EndSend(), but with
EndReceive() it is 100% reproducible.

Michael

<de***************@gmx.netwrote in message
news:11*********************@n35g2000prd.googlegro ups.com...
Greetings all.

Here's a problem that's been driving me nuts for the last 48 hours.
I'm hoping that someone has come across this before.

I have a C# Application that reads a UDP broadcast (asynchronously).
Then it repackages these UDP packets and sends them to a subscriber
via TCP.

Now, I can read the UDP stream all day long without the application
ever using more memory. Everything get's GC'ed just fine.

If I connect a subscriber, and start dispatching the incoming packets
via BeginSend() everything goes according to plan.. for a short while.
Suddenly the application memory consumption starts increasing... and
I've profiled the memory with ".NET Memory Profiler".
It seems that there are many instances of something called
"OverlappedData" accumulating, which I think they mean to be:
"NativeOverlapped".
These are created, but never collected by the GC.

Yes.. I am calling "EndSend()" on the callback from "BeginSend()" in
case you are wondering.
But here's the thing... I've implemented a counter that increments
each BeginSend() dispatch and one counter that increments each
EndSend() callback. After a while I start seeing small differences
that do not go away after the GC kicks in, indicating that a few
Begins were naughty and didn't call back!!

I've googled everywhere and chased up any reference on resource leaks
in Async I/O under .NET but found nothing that indicated that
callbacks might get lost.

I'm at the end of my wits here. Hualp!! Has anyone ever encountered
something similar?

Many thanks in advance,

Dennis Richardson

PS: I've tried this under Windows Vista (64-bit) & Windows XP (32-
bit), no change whatsoever. I'm sure I'm doing something wrong... but
what?

Apr 25 '07 #3
"Peter Bromberg [C# MVP]" wrote:
Can you post a "short but complete" block of working sample code to
illustrate what you are doing that's causing the issue?
Peter
Hello Peter,

Thanks for your response (and Michael too).
Not sure that a working example would be short, but here's basically what
I'm doing:

We have a main Async read loop:

public void OnReceive(IAsyncResult IAR)
{
// Read the data from the socket into the buffer.
// Then dispatch to TCP socket with BeginSend()
tcpSocket.BeginSend(... callback to OnSend);

// Queue next async read
udpSocket.BeginReceiveFrom(... callback to OnReceive);
}

public void OnSend(IAsyncResult)
{
// Do EndSend and be done...
}

Now, I have played around with it some more and discovered the following:

If the next async receive is delayed until the EndSend Callback was called,
then the problem doesn't appear.
(in other words OnReceive ->BeginSend->OnSend->BeginReceive->OnReceive... etc)
So somehow, if there is only one callback active at a time, then there is no
problem. I thought that it might have to do with ThreadPool threads
terminating and hence leaving the callbacks hanging (I saw a tidbit about
that somewhere).

Am I doing something wrong?

Anyway, does anyone have an idea of how to do a rather simple thing like
read UDP socket and push into one or more TCP sockets? Wouldn't one do it
sort of like I described?

I'm happy to provide more details, just don't want to flood the message with
lots of code.

Regards,

Dennis
Apr 25 '07 #4
"Michael Rubinstein" wrote:
Do you experience data loss like packets sent,
but never received by the client?
No, I'm not even worried about the client side at this stage. The server
crashing is enough of a problem.
The memory use creeps up until it reaches a certain limit,
then GC 'wakes up' and reduces the amount
of memory for application use about 2.5 - 3 times and from that moment kept
at lower level then at program start.
Well, these instances of "OverlappedData" (called so by the ".NET Memory
Profiler", I suspect it refers to isntances of NativeOverlapped objects) do
not get collected by the GC (no matter how many generations, full-depth GC
does nothing, so somehow there must be a reference to these things somewhere).
Apr 25 '07 #5
By the way, this guy had the same problem, apparently (didn't get an answer
though):

http://www.thescripts.com/forum/thread236349.html
Apr 25 '07 #6
<de***************@gmx.netwrote in message
news:11*********************@n35g2000prd.googlegro ups.com...
Greetings all.

Here's a problem that's been driving me nuts for the last 48 hours.
I'm hoping that someone has come across this before.

I have a C# Application that reads a UDP broadcast (asynchronously).
Then it repackages these UDP packets and sends them to a subscriber
via TCP.

Now, I can read the UDP stream all day long without the application
ever using more memory. Everything get's GC'ed just fine.

If I connect a subscriber, and start dispatching the incoming packets
via BeginSend() everything goes according to plan.. for a short while.
Suddenly the application memory consumption starts increasing... and
I've profiled the memory with ".NET Memory Profiler".
It seems that there are many instances of something called
"OverlappedData" accumulating, which I think they mean to be:
"NativeOverlapped".
These are created, but never collected by the GC.

Yes.. I am calling "EndSend()" on the callback from "BeginSend()" in
case you are wondering.
But here's the thing... I've implemented a counter that increments
each BeginSend() dispatch and one counter that increments each
EndSend() callback. After a while I start seeing small differences
that do not go away after the GC kicks in, indicating that a few
Begins were naughty and didn't call back!!
That means that the send actually didn't occur , this means that all managed
and unmanaged resources associated with the logical connection (eg. Winsock
buffers) stay allocated which leads to an increased Private bytes
consumption. The GC cannot free this memory, nor should it because the
action did not complete yet. This would also mean that some subscribers
don't receive all of their expected data, right, now the questions are, does
it happen for particular , or arbitrary subscribers, how are they connected
(LAN, WAN, routed switched or both) how do you finally recover from this
(reconnect or restart the server?). Did you fire up a network trace?

Willy.

Apr 25 '07 #7


"Willy Denoyette [MVP]" wrote:
now the questions are, does
it happen for particular , or arbitrary subscribers, how are they connected
(LAN, WAN, routed switched or both) how do you finally recover from this
(reconnect or restart the server?). Did you fire up a network trace?
Thanks for your response Willy.

There's only one subscriber at the moment (haven't even added more than one)
where this happens. The subscriber seems to be fine, no problems on that end.
The two machines are on the same network segement (1GBit/s).

When you say the "sends didn't happen" wouldn't that imply that nothing
further should go through? In other words, the socket should be clogged?
Because that's not what I'm seeing. Yes, some callbacks don't seem to
complete, but the socket still transmits (the correct data).

It's a bit bizarre why this would happen, really, from a performance
standpoint as we are talking about only 1,000 UDP packets repacked into TCP
per second. So that can't be it?
To re-emphasize, this only happens on sending stuff. Receiving works fine
without any glitches.

Regards,

Dennis
Apr 25 '07 #8
Dennis,
No, I'm not even worried about the client side at this stage. The server
crashing is enough of a problem.
does it (crash)?

from your code:
>>>>>>>>>>>>>>>>
We have a main Async read loop:

public void OnReceive(IAsyncResult IAR)
{
// Read the data from the socket into the buffer.
// Then dispatch to TCP socket with BeginSend()
tcpSocket.BeginSend(... callback to OnSend);

// Queue next async read
udpSocket.BeginReceiveFrom(... callback to OnReceive);
}

public void OnSend(IAsyncResult)
{
// Do EndSend and be done...
}
>>>>>>>>>>>
I do very similar things. In my code I call udpSocket.BeginReceiveFrom(...
callback to OnReceive) before tcpSocket.BeginSend(... callback to OnSend).
Any particular reason for placing UDP async read after TCP BeginSend()? My
applications send processed UDP data to multiple TCP clients that connect
and disconnect 'at will'. I am uneasy about a few things in Async Socket
model, but it seems to be working.

Michael

"Dennis Richardson" <De**************@discussions.microsoft.comwrote in
message news:53**********************************@microsof t.com...
"Michael Rubinstein" wrote:
>Do you experience data loss like packets sent,
but never received by the client?
No, I'm not even worried about the client side at this stage. The server
crashing is enough of a problem.
>The memory use creeps up until it reaches a certain limit,
then GC 'wakes up' and reduces the amount
of memory for application use about 2.5 - 3 times and from that moment
kept
at lower level then at program start.
Well, these instances of "OverlappedData" (called so by the ".NET Memory
Profiler", I suspect it refers to isntances of NativeOverlapped objects)
do
not get collected by the GC (no matter how many generations, full-depth GC
does nothing, so somehow there must be a reference to these things
somewhere).

Apr 25 '07 #9
"Michael Rubinstein" wrote:
I do very similar things. In my code I call udpSocket.BeginReceiveFrom(...
callback to OnReceive) before tcpSocket.BeginSend(... callback to OnSend).
Any particular reason for placing UDP async read after TCP BeginSend()?
Thanks Michael. The reason I did it in that order (BeginReceive after
BeginSend) is because I wanted to be reasonably sure that not another
"OnReceive" jumped in there and fired off a BeginSend before this one (which
could then be possible (although probably quite unlikely).
I will give this a try, although I have little hope that it'll make a
difference.

Apr 25 '07 #10
"Dennis Richardson" <De**************@discussions.microsoft.comwrote in
message news:17**********************************@microsof t.com...
>

"Willy Denoyette [MVP]" wrote:
>now the questions are, does
it happen for particular , or arbitrary subscribers, how are they
connected
(LAN, WAN, routed switched or both) how do you finally recover from this
(reconnect or restart the server?). Did you fire up a network trace?

Thanks for your response Willy.

There's only one subscriber at the moment (haven't even added more than
one)
where this happens. The subscriber seems to be fine, no problems on that
end.
The two machines are on the same network segement (1GBit/s).
That means no routers, only a Gigabit switch switch? Also this happens on a
connected socket, here I mean a socket that stays connected for the duration
of the program and does not close/reconnect for each number of transfers.
What's the source of the UDP packets? is it the same "subscriber" machine,
or are they different?
When you say the "sends didn't happen" wouldn't that imply that nothing
further should go through? In other words, the socket should be clogged?
Because that's not what I'm seeing. Yes, some callbacks don't seem to
complete, but the socket still transmits (the correct data).
Well, I really meant that the send did not complete at the application
level, from your description it's clear that all data was correctly
transmitted, only thing is, the callback did not happen, this can be the
result of a failure to signal the IOC port (kernel space), but it can also
be a problem at a lower level in the kernel or on the network stack, for
instance with the NIC's driver code or the NDIS, IP, TCP or Winsock code.
Point is, your EndSend is never called so the underlying resources (managed
and unmanaged) are never freed (well, only when the process ends).
Don't know if you can test at a lower rate, say 100MB/sec and try again, if
the problem remains you can (possibly) exclude Gigabit related issues
(timing problems in the NIC and switches) and take a closer look at your
code, if the problem goes away, maybe you can try to replace the NIC (and
the switch) and find out with the vendor(s) whether this is not a known
problem.
It's a bit bizarre why this would happen, really, from a performance
standpoint as we are talking about only 1,000 UDP packets repacked into
TCP
per second. So that can't be it?
No, at least it shouldn't, don't know what would happen when you only send
data over TCP to the subscriber, say you simulate that repacking of UDP
messages into TCP streams and send these asynchronously.

I don't know if you could post a small but complete sample that illustrates
the issue, I have a similar Gigabit set-up which I could use to try it out
myself.
To re-emphasize, this only happens on sending stuff. Receiving works fine
without any glitches.
Willy.

Apr 25 '07 #11


"Willy Denoyette [MVP]" wrote:
What's the source of the UDP packets? is it the same "subscriber" machine,
or are they different?
Same subscriber machine. There's a process there that multicasts only on
this machine (can't do anything about this, out of my control). Don't think
that's the issue though?

I don't know if you could post a small but complete sample that illustrates
the issue, I have a similar Gigabit set-up which I could use to try it out
myself.
I will try to put something together. It's pretty clear to me that I'm doing
something wrong else I would encounter this "issue" more frequently on my web
searches. After all, applications that communicate via UDP and TCP are rather
common.

Do you see any issue dispatching the BeginSend from the OnReceive callback?

Regards,

Dennis
Apr 25 '07 #12
Okay, some more investigative results:

It seems that the problem might be that packets arrive too fast (at peak
load) sometimes for .NET to be able to handle repacking it into TCP. Baseload
might only be 1000 messages per second, but I think peak throughput might
exceed that by an order of magnitude.

I can simulate the same behavior by calling BeginSend a few times per
OnReceive. This just seems to swamp the framework with NativeOverlapped
instances that it doesn't collect.

The collection can be enforced by calling GC.Collect() many many times. Per
each GC(2nd generation) sweep, a few of them get removed. After a dozen or
so, manually triggered, rapid-fire GCs, they get collected. But that can be
hardly the point. It sees the CLR has problems freeing these for some reason.

I'm sort of stumped now what to do really? Maybe I should architect
differently?
Apr 26 '07 #13
Dennis, does your program actually run out of memory or you just assumed
it eventually will? Forcing GC.Collect() is never a good idea. In my
experience GC works best when the application code does not interfere
directly. I would be more concerned about packets sent but never received by
the TCP client. This would be a clear indication that something is wrong.
>
Maybe I should architect differently?
>
You could store incoming udp packets to a temporary buffer until it either
reaches a certain byte limit or a preset time interval expires, and then
BeginSend() the bundle at once. I am basically in 'the same boat'. I did not
take this approach jet because at the current work load my server seems to
manage. It would be more complex in my case. My udp packets are re-routed to
specific clients, one packet may be sent to one group of clients, the next
to a different group, and so on.

Michael

"Dennis Richardson" <De**************@discussions.microsoft.comwrote in
message news:B1**********************************@microsof t.com...
Okay, some more investigative results:

It seems that the problem might be that packets arrive too fast (at peak
load) sometimes for .NET to be able to handle repacking it into TCP.
Baseload
might only be 1000 messages per second, but I think peak throughput might
exceed that by an order of magnitude.

I can simulate the same behavior by calling BeginSend a few times per
OnReceive. This just seems to swamp the framework with NativeOverlapped
instances that it doesn't collect.

The collection can be enforced by calling GC.Collect() many many times.
Per
each GC(2nd generation) sweep, a few of them get removed. After a dozen or
so, manually triggered, rapid-fire GCs, they get collected. But that can
be
hardly the point. It sees the CLR has problems freeing these for some
reason.

I'm sort of stumped now what to do really? Maybe I should architect
differently?

Apr 26 '07 #14
"Dennis Richardson" <De**************@discussions.microsoft.comwrote in
message news:B1**********************************@microsof t.com...
Okay, some more investigative results:

It seems that the problem might be that packets arrive too fast (at peak
load) sometimes for .NET to be able to handle repacking it into TCP.
Baseload
might only be 1000 messages per second, but I think peak throughput might
exceed that by an order of magnitude.
I could be wrong, but it looks like you are exhausting the IOC thread pool!
This pools has a max. of 1000 threads, did you ever inspect (using
ThreadPool.GetAvailableThreads ) the number of IO threads remaining in the
pool when receiving the UDP packets? Or simply did you ever inspect the
number of threads in the process?
I would love to see some code, really.

Willy.

Apr 26 '07 #15
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote
I would love to see some code, really.
I second that.

I'm suspicious of something strange going on in your code. With overlapped
structures sitting around not being collected, and sockets not responding
quickly enough, something weird is happening.

--
Chris Mullins, MCSD.NET, MCPD:Enterprise, Microsoft C# MVP
http://www.coversant.com/blogs/cmullins
Apr 26 '07 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Alex | last post by:
Hi, I am programming asynchronous communication between client and server, with .net asynchronous sockets example from MSDN...
6
by: roger beniot | last post by:
I have a program that launches multiple threads with a ThreadStart method like the following (using System.Net.Sockets.Socket for UDP packet transfers to a server): ThreadStart pseudo code: ...
3
by: Adam Clauss | last post by:
There seems to be various methods to determine when the remote client disconnects, but all of them I have seen are Synchronous. AKA: Right before you try to send or receive data, check. Is there...
5
by: John Sheppard | last post by:
Hi all, I am not sure that I am posting this in the right group but here it goes anyway. I am new to socket programming and I have been searching on the internet to the questions I am about to pose...
4
by: Engineerik | last post by:
I am trying to create a socket server which will listen for connections from multiple clients and call subroutines in a Fortran DLL and pass the results back to the client. The asynchronous socket...
11
by: atlaste | last post by:
Hi, In an attempt to create a full-blown webcrawler I've found myself writing a wrapper around the Socket class in an attempt to make it completely async, supporting timeouts and some scheduling...
14
by: =?Utf-8?B?TWlrZVo=?= | last post by:
I have a sync socket application. The client is blocked with Socket.Receive(...) in a thread, another thread calls Socket.Close(). This unblock the blocked thread. But the socket server is still...
10
by: ThunderMusic | last post by:
Hi, I'm currently working with sockets. I accept connections using m_mySocket.Listen(BackLogCount); But when I want to stop listening, I shutdown all my clients and call m_mySocket.Close(), but it...
2
by: dougmcmurtry | last post by:
I have an Asynchronous socket that sends data to a server for credit card approvals. The socket is kept alive by the server through a heartbeat that sends a "beat" every 90 seconds. Trouble is that...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.