2

So this is a .NET CF 3.5 app, running on CE7. The problem is also visible in CE5.

We use HttpWebRequests to query a server. When online, all seems well.

When server is unavailable, we observe what appears to be a resource leak.

Using the CF remote performance monitor, we can see tens of thousands of weak references pile up (eventually), never going away. Occupying loads of memory. The heap grows linearly. See screenshots.

They're all marked as roots, and finalizer. I get the feeling the finalizer for the webrequest is not working properly somehow, but not quite sure how to interpret all this.

When the request is complete (or an exception happens) we dispose of the IDisposables on the request (the request stream and response stream).

Could you explain what is going on here please? Why are all those weakreferences accumulating and not getting garbage collected? Any insight appreciated.

Thanks.

RMP RMP RMP RMP

EDIT:

It's probably also worth mentioning, that in the debugger, we occasionally see this ObjectDisposedException exception, which is uncaught, and brings down the app (since its on Threadpool thread). Only occasionally. May/may not be related to above leak. We've tried every variant of using/disposing/not disposing/closing of the streams we can, and every bit of found advice on this,to no avail.

   at System.Threading.Timer.throwIfDisposed()
   at System.Threading.Timer.Change(UInt32 dueTime, UInt32 period)
   at System.Threading.Timer.Change(Int32 dueTime, Int32 period)
   at System.Net.HttpWebRequest.startReadWriteTimer()
   at System.Net.HttpWebRequest.ConnectionClient.Read(Byte[] data, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.NetworkRead(Byte[] data, Int32 offset, Int32 length)
   at System.Net.ContentLengthReadStream.doRead(Byte[] data, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.ReadToDrain(Byte[] buffer, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.doClose()
   at System.Net.ContentLengthReadStream.doClose()
   at System.Net.HttpReadStream.Finalize()
Nik
  • 2,718
  • 23
  • 34
  • 2
    Can you show some example code where you are creating and releasing those weak references? – brainless coder Jun 23 '14 at 05:49
  • @Nik - It's not really going to be possible to help without some portion of code showing how you make the HttpWebRequest calls. I doubt anything is wrong with HttpWebRequest, it's more likely just an issue with how you call it and handle exceptions in this case (particularly since you're getting piled up WebExceptions... I wonder if you're making a new HttpWebRequest in your exception handler, effectively leading to infinite recursion and an inability to collect requests further up the stack). – huntharo Jun 25 '14 at 14:31

1 Answers1

0
  1. ObjectDisposedException

According to MSDN, in the Compact Framework

[a] request stream with zero content length causes an ObjectDisposedException if it was not obtained and closed correctly. To handle zero-content-length requests, you must explicitly call the GetRequestStream method and then call the Close method on the returned stream without calling the Write method...

However they don't tell you if any data has been sent you'll receive an exception when calling the Close method ("This operation cannot be performed after the request has been submitted"). So I needed to do this:

using (Stream httpWebRequestStream = httpWebRequest.GetRequestStream())
{
<other transmission code, including write if there's data>

    if (httpWebRequest.ContentLength == 0)
    {
        Log.Debug("httpWebRequest stream Close:");
        httpWebRequestStream.Close();
    }
}
  1. Memory leaks

I think there may still be some in my code, but I've tried to ameliorate them with this later code:

httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;

<handle response>

httpWebResponse.GetResponseStream().Close();
httpWebResponse.Close();
httpWebResponse = null;

httpWebRequest = null;

And this in the catch block:

if (httpWebResponse != null)
{
    httpWebResponse.GetResponseStream().Close();
    httpWebResponse.Close();
    httpWebResponse = null;
}
if (httpWebRequest != null)
{
    httpWebRequest = null;
}
hemisphire
  • 1,205
  • 9
  • 19