Problem disposing of socket / finalising twice? - c#

I'm working with some code (not mine I hasten to add, I don't trust this much at all) for a class which opens a socket, makes requests and listens for responses, which is throwing an exception in a way I can't comprehend when tested in xunit. I assume the same exception happens "live" but the class is referenced by a singleton so it is probably just hidden.
The problem manifests as "System.CannotUnloadAppDomainException: Error while unloading appdomain" in xunit and the inner exception is "System.ObjectDisposedException" thrown (essentially) inside the finaliser when closing the socket! There are no other reference to the socket which call close and dispose is protected on the Socket class so I'm not clear how else the object could be disposed.
Further, if I merely catch and absorb the ObjectDisposedException xunit terminates when it hits the line to close the listener thread.
I just don't get how the Socket can be disposed before it's asked to close.
My knowledge of sockets is only what I've learnt since finding this problem, so I don't know if I've provided everything SO might need. LMK if not!
public class Foo
{
private Socket sock = null;
private Thread tListenerThread = null
private bool bInitialised;
private Object InitLock = null;
private Object DeInitLock = null;
public Foo()
{
bInitialised = false;
InitLock = new Object();
DeInitLock = new Object();
}
public bool initialise()
{
if (null == InitLock)
return false;
lock (InitLock)
{
if (bInitialised)
return false;
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 8);
sock.Bind( /*localIpEndPoint*/);
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(mcIP));
tListenerThread = new Thread(new ThreadStart(listener));
tListenerThread.Start();
bInitialised = true;
return true;
}
}
~Foo()
{
if (bInitialised)
deInitialise();
}
private void deInitialise()
{
if (null == DeInitLock)
return;
lock (DeInitLock)
{
if (bInitialised)
{
sock.Shutdown(SocketShutdown.Both); //throws System.ObjectDisposedException
sock.Close();
tListenerThread.Abort(); //terminates xunit test!
tListenerThread = null;
sock = null;
bInitialised = false;
}
}
}
}

If this object is eligible for garbage collection and there are no other references to the Socket, then the socket's finalizer may well run before your object's finalizer. I suspect that's what's happened here.
It's generally a bad idea (IMO) to do this much work in a finalizer. I can't remember the last time I implemented a finalizer at all - if you implement IDisposable, you should be fine unless you have direct references to unmanaged resources, which are almost always in the form of IntPtrs. Orderly shutdown should be the norm - a finalizer should only usually run if either the program is shutting down, or someone has forgotten to dispose of the instance to start with.
(I know you clarified at the start that this isn't your code - I just thought I'd explain why it's problematic. Apologies if you already knew some/all of this.)

Because of the way the garbage collector and finalizers work, finalizers must only be used if your class is the direct owner of an unmanaged resource such as a Window Handle, a GDI object, a global handle or any other kind of IntPtr.
A finalizer must not try to dispose or even use a managed resource or you will risk calling a finalized or disposed object.
I highly recommend you to read this very important Microsoft article for more detail on how garbage collection works. Also, this is the MSDN reference on Implementing Finalize and Dispose to Clean Up Unmanaged Resources, look carefully for the recommendations at the bottom.
In a nutshell:
If your object is holding an unmanaged resource, you should implement IDisposable and you must implement Finalizer.
If your object is holding an IDiposable object, it should also implements IDisposable on it's own and dispose that object explicitly.
If your object is holding both an unmanaged and a disposable, the finalizer must call two diferent version of Dispose, one that release disposable and unmanaged, the other only unmanaged. This is usually done using a Dispose(bool) function called by Dipose() and Finalizer().
The Finalizer must never use any other resource than the unmanaged resource being released and self. Failing to do so will risk referencing collected or disposed objects, since an object is temporarily ressurected prior to finalization.

New info: this looks like I'm having two problems actually, but the thread one appears to be rather toxic.
From the MSDN link above:
"ThreadAbortException is a special
exception that can be caught, but it
will automatically be raised again at
the end of the catch block."
Some very interesting community content also at that link including "Thread.Abort is a Sign of a Poorly Designed Program".
So at least I have some ammo to get this changed now :)

Related

Unmanaged Leak in Calling Web service in C#

I need help with my code.
Ive been trying to use RedGate to monitor the memory usage of my application, after hours of testing It pointed out the unmanaged code of my application, and I could only think of my webservice calling as the only or somewhat unmanaged part of my code. Ive been debugging for hours and cant seem to find out where or what really happened. below is my code.
private void btnstart_Click(object sender, EventArgs e)
{
btnPressed = !btnPressed //boolean
if(btnPressed)
{
myTask = Task.Factory.StartNew(() =>
{
do {
_checkMatches(token.Token);
} while (token.IsCancellationRequested != true);
},token.Token);
}
else
{
token.Cancel();
try {
Task.WaitAny(myTask);
}
catch(Exception Error) {
//Put to logs
}
finally
{
if(myTask.isCancelled || myTask.IsCompleted || myTask.IsFaulted)
{
myTask.Dispose();
}
}
}
}
private void _checkMatches(CancellationToken token)
{
try
{
if(token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
EndpointAddressBuilder ServiceEndPoint = new EndpointAddressBuilder(//Read Endpoint From Notepad);
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });//just bypassing validation for test purposes
// WebService is an ASMX web service
using (WebService.SoapClient client = new WebService.SoapClient())
{
WebService.checkResponse clientRes = client.checkClient();
if(clientRes.response == 1 || clientRes.response == 2) {
//Put to Logs
}
}
}
catch(Exception error){
//Put to logs
}
}
I cant seem to find any error in this code. Can Someone Help me with what is the problem why my unmanaged code is leaking? or could someone suggest what tools to be used or even suggest to find the leaking part of my code? Any Help would be great.
If you are using RedGate memory profiler it should tell you more than just pointing unmanaged resources. Because you are not directly creating any unamanged resources, most likely your memory leak is caused by a managed object or an event subsciption(or callback subscription).
Standard .net managed objects which have unmanaged resources (ie : WebService.SoapClient) have implemented the finalizer(destructor) in order to get rid of its unmanaged resources in any case if Dispose is not called. If you use a standard .net managed object which has unmanaged resources and don't call the dispose (this is bad), still it will release unamanged resources when it is going through the finalization. Generally this shouldn't cause unmanaged resource memory leak.
How to check if there is any memory leak:
Execute your memory consumption logic a few times. Go to the Instance list and see if there is any instances are growing. Select the 'Objects with Source' option in order to get rid of heaps of system object. You should see more instances that there should be if there is any memory leak.
If there is any growing instances, pick one and see the objects retention graph which will show you exactly which instance holds the reference.
And also, make sure that you have implemented IDisposable properly and dispose all disposable objects and unsubscribe from all event subscriptions.
Have a look at below walkthroughs
http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/walkthrough http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/

Why do bitmaps stay in memory unless I call GC.Collect?

I'm developing an application that connects to a GigEVision camera, and pulls images from it. I'm currently using the Pleora eBus SDK with C#.NET.
The code below is just a test application for the camera connection - it can stream images, but rapidly runs out of memory unless I call GC.Collect();
It's worth noting the images being streamed are large (4096x3072), so the crash happens fairly quickly.
I suspected at first that not calling Dispose() was the issue. However, I can call Dispose() on each image right before getting rid of the reference to it, and that did not fix the issue.
I've also tried explicitly releasing the buffers that come into the display thread callback, but that had no effect.
Can I get my memory back in a more elegant way?
using System;
using System.Windows.Forms;
using PvDotNet;
using PvGUIDotNet;
using System.Drawing;
namespace eBus_Connection
{
public partial class MainForm : Form
{
PvDeviceGEV camera;
PvStreamGEV stream;
PvPipeline pipeline;
PvDisplayThread thread;
bool updating = false;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Shown(object sender, EventArgs e)
{
PvDeviceInfo info;
PvDeviceFinderForm form = new PvDeviceFinderForm();
form.ShowDialog();
info = form.Selected;
camera = PvDeviceGEV.CreateAndConnect(info) as PvDeviceGEV;
stream = PvStreamGEV.CreateAndOpen(info.ConnectionID) as PvStreamGEV;
pipeline = new PvPipeline(stream);
if (camera == null || stream == null)
throw new Exception("Camera or stream could not be created.");
camera.NegotiatePacketSize();
camera.SetStreamDestination(stream.LocalIPAddress, stream.LocalPort);
camera.StreamEnable();
camera.Parameters.ExecuteCommand("AcquisitionStart");
pipeline.Start();
thread = new PvDisplayThread();
thread.OnBufferDisplay += thread_OnBufferDisplay;
thread.Start(pipeline, camera.Parameters);
status.DisplayThread = thread;
status.Stream = stream;
}
void thread_OnBufferDisplay(PvDisplayThread aDisplayThread, PvBuffer aBuffer)
{
Bitmap b = new Bitmap((int)aBuffer.Image.Width, (int)aBuffer.Image.Height);
aBuffer.Image.CopyToBitmap(b);
BeginInvoke(new Action<Bitmap>(ChangeImage), b);
}
void ChangeImage(Bitmap b)
{
if (PictureBox.Image != null)
PictureBox.Dispose();
PictureBox.Image = b;
GC.Collect();//taking this away causes memory to leak rapidly.
}
}
}
It's very likely that somewhere in your code an Image such as a Bitmap is not being disposed. Bitmap extends Image which implements IDisposable which means you need to call Dispose() on it when you're done with it (often by wrapping it with a using statement). You aren't disposing the Bitmap or Image somewhere so the GC finalizes it when it can (or in this case when you explicitly invoke the GC).
Once the GC determines that a class is no longer referenced, it becomes available to clean up... Before cleaning it up, it checks for a finalizer. If a finalizer exists, the class is placed in a special GC finalizer queue that will run the finalizer before cleaning up the resources/memory. Most IDisposable classes have finalizers which allow the GC to do the Dispose() call work in case you forgot to manually dispose the class yourself. It seems that this is what is happening to your code, but without seeing ALL classes I can only guess what isn't disposed (and no idea where).
EDIT: I do have a guess though. I bet the PictureBox.Dispose() call does not dispose PictureBox.Image
If an object implements IDisposable then you should absolutely call Dispose on it but disposing an object doesn't release the memory it occupies. It releases things like, in this case, an image handle. Such resources have to be released first, before memory can be reclaimed, so disposing still helps.
When the GC runs, if an object hasn't been disposed then it must first finalise it, meaning that it must wait longer to reclaim the memory. If the object has been disposed, memory is reclaimed as soon as the GC runs.
The GC runs in the background though. If your application is busy allocating more and more memory then the GC never gets a chance to run and reclaim it, regardless of whether you dispose objects or not. In such cases, you need to invoke the GC explicitly from time to time. Creating multiple images is the most common scenario that requires explicit GC invocation.
It's worth noting that ALL objects remain in memory until the GC runs and cleans them up, whether the object implements IDisposable or not. You normally don't notice it though, because most apps have enough down-time to allow the GC to run implicitly and reclaim that memory. There's nothing special about your Bitmap objects in this regard.
You are disposing the picture box instead of the image. Even if that will dispose the image in the picture box, it will only do that the first time. After that the picture box is in a disposed state and calling Dispose again will do nothing.
You should get the image reference from the picture box and dispose it once it's not used any more:
void ChangeImage(Bitmap b) {
Image oldImage = PictureBox.Image;
PictureBox.Image = b;
if (oldImage != null) {
oldImage.Dispose();
}
}
A bitmap that isn't disposed correctly have to be finalized before it can be collected. There is a background thread that finalizes objects that needs to be collected, but if you abandon objects faster than that thread can take care of them, you will run out of memory.
When the bitmap is disposed correctly, it becomes a regular managed object that can be collected right away whenever the garbage collector wants to.

C# garbage collector seems to be closing my StreamWriter too early

I have a logger class thats a singleton. In it's destructor I call Close() which prints the footer for the log and then closes the StreamWriter.
public void Close()
{
WriteLogFileFooter();
_logFile.Flush();
_logFile.Close();
}
The problem is when System.Enviornment.Exit(1) is called from elsewhere in the program (portions that I didn't write myself), the footer is never printed and my logger throws an exception for trying to write to a closed stream. I can only assume the Exit command is causing my StreamWriter to be closed before my Singleton is destructed. I tried to use GC.SupressFinalize() on my StreamWriter but that didn't seem to help.
You are violating one explicit rule for finalizers:
The Finalize method should not reference any other objects.
http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=VS.90).aspx
It's entirely possible that the managed object you hold a reference to is collected before your object is collected when the application exits.
UPDATE
If you need to clean up managed resources when the application exits, you could hook up the ProcessExit event of AppDomain rather than rely on non-deterministic behavior of finalizer execution.
.NET Console Application Exit Event
You should make your logger implement IDisposable, and use it in a using block. This means that it will be deterministically disposed, whereas now it is being nondeterministically destructed.
The cause of the error is that your stream will sometimes be closed before the logger, as Exit basically destroys everything (nondeterministically) and quits. You should use a deterministic pattern (IDisposable) to avoid this.
In reality, destructors are rarely useful in C#, for the precise reason that they are non-deterministic. They only are worth using for releasing unmanaged resources.
Also, implementing IDisposable may make it inconvenient to use a singleton. I personally think it's better to create an instance to be used throughout the program and disposed at the end, rather than an explicit singleton.
As others have already clearly stated, you should not attempt to access your _logFile object at all from your logger class' finalizer. You shouldn't access any other objects in a finalizer, because the Garbage Collector might already have wiped them out of existence.
I think you could avoid your problem by a few simple steps:
Get rid of your current finalizer.
Perform a _logFile.Flush after every single write, instead of waiting until the very end of your logger object's lifetime when it might already be too late.
Flushing a log file stream frequently seems legitimate to me because the whole point of having a log is using it to find, and deal with, situations where errors have occurred. If your process is suddenly terminated by an exceptional situation, your log should still be as complete as possible; thus flushing the log stream buffer frequently seems a sensible thing to do.
Make your logger implement IDisposable (this MSDN Magazine article will explain to you how this is done) and close your log file stream from there.
I had the same problems and my solution was as follows:
When creating the FileStream in the constructor of your class used GC.SuppressFinalize immediately. This makes you responsible for cleaning the stream
Close the stream in the Dispose() of the class
public class LogFileEventListener : IDisposable
{
private bool disposed = false;
private FileStream fileStream;
public LogFileEventListener(string path)
{
//Opens a new file stream to log file
this.fileStream = new FileStream(path, FileMode.Append, FileAccess.Write);
GC.SuppressFinalize(this.fileStream);
}
/// <summary>Finalize the listener</summary>
~LogFileEventListener() { this.Dispose(); }
/// <summary>Disposes the listener</summary>
public override void Dispose()
{
try
{
if (!this.disposed)
{
/* Do you stuff */
//Close the log file
if (this.fileStream != null)
{
this.fileStream.Close();
this.fileStream = null;
}
base.Dispose();
}
}
finally
{
this.disposed = true;
GC.SuppressFinalize(this);
}
}
}
Most likely the StreamWriter is being closed else where.
Try creating an additional StreamWriter in your singleton's constructor, write to it a few times (to confirm that it is working), then write to it again in the destructor before calling close (close will also flush).
If the above works then you will know some other code is closing your log. If it does not work then you will know that it is a .NET thing (possibly having something to do with how/where the variable is referenced).
According to the documentation, you should be able to work around the issue by putting the StreamWriter in a base class. This of course will not work for you because your test case is not a standard finalization, but is a program exit, meaning .NET does what it wants when it wants. Instead, you should catch the exit event, dispose of this class, then return, to guarantee that things are disposed in the correct order. You should also check if the StreamWriter is already closed in the finalizer in case the program aborts due to an error.

How to clean up COM references in .NET when app will be left running?

I am working on a .NET program that starts a new instance of Excel, does some work, then ends, but must leave Excel running. Later, when the program runs again, it will attempt to hook into the previous instance.
What is the best way to handle the releasing of COM objects in this situation? If I do not do a "ReleaseComObject" on the app object the first time, then on the second run get the active object, then finally release the com object, do I have a memory leak?
The following simplified code illustrates what I am trying to do:
private Microsoft.Office.Interop.Excel.Application xlsApp;
private Microsoft.Office.Interop.Excel.Workbook xlsWb;
public void RunMeFirst()
{
//Start a new instance
System.Type oSEType = Type.GetTypeFromProgID("Excel.Application");
xlsApp = Activator.CreateInstance(oSEType);
xlsWb = xlsApp.Workbooks.Open("C:\\test1.xls");
//Do some stuff
xlsWb.Close(false);
Cleanup(ref xlsWb);
//Do not quit Excel here
//No Cleanup of xlsApp here? Is this OK?
System.Environment.Exit(0);
}
public void RunMeSecond()
{
//Hook into existing instance
xlsApp = Marshal.GetActiveObject("Excel.Application");
xlsWb = xlsApp.Workbooks.Open("C:\\test2.xls");
//Do some stuff
xlsWb.Close(false);
Cleanup(ref xlsWb);
xlsApp.Quit();
Cleanup(ref xlsApp);
System.Environment.Exit(0);
}
public void Cleanup(ref object theObj)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(theObj);
theObj = null;
}
Thanks
In general, when working with the Office PIAs, i've found that these sorts of problems with objects not being released arise when you have instance variables that hold COM objects. In your case, these would be xlsApp and xlsWb. You don't have to quit the Excel application in order to release the objects, but you do have to perform the following as a cleanup procedure:
Marshal.FinalReleaseComObject(xlsWb);
xlsWb = null;
Marshal.FinalReleaseComObject(xlsApp);
xlsApp = null;
GC.Collect();
Local-scoped variables containing COM objects don't seem to cause this problem, only instance variables. I hope this helps!
I'm a tad confused - at the end of RunMeFirst you exit the process, so is RunMeSecond run in a different process from the first method or the same process?
Either way I would change your code so that xlsWb is scoped locally and just do the following:
public void RunMeFirst()
{
System.Type oSEType = Type.GetTypeFromProgID("Excel.Application");
xlsApp = Activator.CreateInstance(oSEType);
Workbook xlsWb = xlsApp.Workbooks.Open("C:\\test1.xls");
// Do stuff
xlsWb.Close(false);
System.Environment.Exit(0);
}
You shouldn't really call any of the ReleaseComObject methods except in certain circumstances (for example in server applications where many COM objects will all be in use and so it is critical to release objects as soon as possible). The usual mechanism for cleaning up COM object should simply be to let them go out of scope, in which case the COM object will be released using the same magic the GC uses (I believe that it is cleaned up as the finalizer is run, but I'm not 100% sure on this).
The reason why its a good idea to scope xlsWb locally (rather than as a class member or a static member) is that class members will only be cleaned up when the class is cleaned up, and static members are never cleaned up until the appdomain is unloaded. If you do need to clean up a COM object referenced by a static field then the way to do this is to set the static field to null so the underlying COM object can be cleaned up by the GC scoping rules:
xlsWb = null;
Also there should be no real need to call GC.Collect for similar reasons - Mike Rosenblum gives a fair explanation as to why he's calling GC.Collect and ReleaseComObject, but no real justification as to why he isn't just satisfied with letting the garbage collector do its job. Like I said, there are situations where you might want more control over the release of COM objects, however these are the exception not the rule.
You may also find reading Marshal.ReleaseComObject Considered Dangerous useful.

Can't Re-bind a socket to an existing IP/Port Combination

Greetings, I'm trying to find a way to 'unbind' a socket from a particular IP/Port combination. My pseudocode looks like this:
ClassA a = new ClassA(); //(class A instantiates socket and binds it to 127.0.0.1:4567)
//do something
//...much later, a has been garbage-collected away.
ClassA aa = new ClassA(); //crash here.
At this point, .Net informs me that I've already got a socket bound to 127.0.0.1:4567, which is technically true. But no matter what code I put in ClassA's destructor, or no matter what functions I call on the socket (I've tried .Close() and .Disconnect(true)), the socket remains proudly bound to 127.0.0.1:4567. What do I do to be able to 'un-bind' the socket?
EDIT: I'm not relying solely on garbage collection (though I tried that approach as well). I tried calling a.Close() or a.Disconnect() and only then instantiating aa; this doesn't solve the problem.
EDIT: I've also tried implementing IDisposable, but the code never got there without my calling the method (which was the equivalent of earlier attempts, as the method would simply try .Close and .Disconnect). Let me try calling .Dispose directly and get back to you.
EDIT (lots of edits, apologies): Implementing IDisposable and calling a.Dispose() from where 'a' loses scope doesn't work - my Dispose implementation still has to call either .Close or .Disconnect(true) (or .Shutdown(Both)) but none of those unbind the socket.
Any help would be appreciated!
(this is what finally got everything to work for me)
Make sure EVERY socket that the socket in A connects to has
socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress, true);
set upon being initiated.
you can't rely on object being garbage collected in C# (i assume you're using c#, based on tagging) if it holds resources like being bound to the network resource like in your example, or holding some other kind of stream, a file stream would be a common example.
you have to assure to release the resources that the object is holding, so that it can be garbage collected. otherwise it won't be garbage collected, but remain living somewhere in the memory. your pseudocode example doesn't provide that you're doing the resources releasing, you just state that the object gets (should get) garbage collected.
The garbage collector doesn't guarantee you that the socket will ever be closed. For a complete example read this MSDN example.
The main point is to actually call Socket.Close() as soon as possible. For example, ClassA could implement IDisposable and use it like this:
using (ClassA a = new ClassA())
{
// code goes here
}
// 'a' is now disposed and the socket is closed
The garbage collector runs the finalizer of the object at some indeterminate time.
You could implement the IDisposable interface and call the Dispose() method before the object looses Scope - or let the using statement do that for you.
see http://msdn.microsoft.com/en-us/library/system.idisposable.aspx and http://msdn.microsoft.com/en-us/library/yh598w02.aspx
edit: works fine for me
using System;
using System.Net.Sockets;
using System.Net;
namespace ConsoleApplication1
{
class Program
{
class ClassA : IDisposable
{
protected Socket s;
public ClassA()
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Bind(new IPEndPoint(IPAddress.Any, 5678));
}
public void Dispose()
{
s.Close();
}
}
static void Main(string[] args)
{
using(ClassA a=new ClassA()) {
}
using (ClassA b = new ClassA())
{
}
}
}
}
The best solution is to retry to bind the socket a few times (2-3). On the first attempt, if it fails, i have found that it will properly (and permanently) close the original socket.
HTH,
_NT

Categories