In a library I've created, I have a class, DataPort, that implements functionality similar to the .NET SerialPort class. It talks to some hardware and will raise an event whenever data comes in over that hardware. To implement this behavior, DataPort spins up a thread that is expected to have the same lifetime as the DataPort object. The problem is that when the DataPort goes out of scope, it never gets garbage collected
Now, because DataPort talks to hardware (using pInvoke) and owns some unmanaged resources, it implements IDisposable. When you call Dispose on the object, everything happens correctly. The DataPort gets rid of all of its unmanaged resources and kills the worker thread and goes away. If you just let DataPort go out of scope, however, the garbage collector will never call the finalizer and the DataPort will stay alive in memory forever. I know this is happening for two reasons:
A breakpoint in the finalizer never gets hit
SOS.dll tells me that the DataPort is still alive
Sidebar: Before we go any further, I'll say that yes, I know the answer is "Call Dispose() Dummy!" but I think that even if you let all references go out of scope, the right thing should happen eventually and the garbage collector should get rid of the DataPort
Back to the Issue: Using SOS.dll, I can see that the reason my DataPort isn't being garbage collected is because the thread that it spun up still has a reference to the DataPort object - through the implicit "this" parameter of the instance method that the thread is running. The running worker thread will not be garbage collected, so any references that are in the scope of the running worker thread are also not eligible for garbage collection.
The thread itself runs basically the following code:
public void WorkerThreadMethod(object unused)
{
ManualResetEvent dataReady = pInvoke_SubcribeToEvent(this.nativeHardwareHandle);
for(;;)
{
//Wait here until we have data, or we got a signal to terminate the thread because we're being disposed
int signalIndex = WaitHandle.WaitAny(new WaitHandle[] {this.dataReady, this.closeSignal});
if(signalIndex == 1) //closeSignal is at index 1
{
//We got the close signal. We're being disposed!
return; //This will stop the thread
}
else
{
//Must've been the dataReady signal from the hardware and not the close signal.
this.ProcessDataFromHardware();
dataReady.Reset()
}
}
}
The Dispose method contains the following (relevant) code:
public void Dispose()
{
closeSignal.Set();
workerThread.Join();
}
Because the thread is a gc root and it holds a reference to the DataPort, the DataPort is never eligible for the garbage collection. Because the finalizer is never called, we never send the close signal to the worker thread. Because the worker thread never gets the close signal, it keeps going forever and holding that reference. ACK!
The only answer I can think of to this problem is to get rid of the 'this' parameter on the WorkerThread method (detailed below in the answers). Can anybody else think of another option? There must be a better way to create an object with a thread that has the same lifetime of the object! Alternatively, can this be done without a separate thread? I chose this particular design based on this post over at the msdn forums that describe some of the internal implementation details of the regular .NET serial port class
Update a bit of extra information from the comments:
The thread in question has IsBackground set to true
The unmanaged resources mentioned above don't affect the problem. Even if everything in the example used managed resources, I would still see the same issue
To get rid of the implicit "This" parameter, I changed the worker thread method around a bit and passed in the "this" reference as a parameter:
public static void WorkerThreadMethod(object thisParameter)
{
//Extract the things we need from the parameter passed in (the DataPort)
//dataReady used to be 'this.dataReady' and closeSignal used to be
//'this.closeSignal'
ManualResetEvent dataReady = ((DataPort)thisParameter).dataReady;
WaitHandle closeSignal = ((DataPort)thisParameter).closeSignal;
thisParameter = null; //Forget the reference to the DataPort
for(;;)
{
//Same as before, but without "this" . . .
}
}
Shockingly, this did not solve the problem!
Going back to SOS.dll, I saw that there was still a reference to my DataPort being held by a ThreadHelper object. Apparently when you spin up a worker thread by doing Thread.Start(this);, it creates a private ThreadHelper object with the same lifetime as the thread that holds onto the reference that you passed in to the Start method (I'm inferring). That leaves us with the same problem. Something is holding a reference to DataPort. Let's give this one more try:
//Code that starts the thread:
Thread.Start(new WeakReference(this))
//. . .
public static void WorkerThreadMethod(object weakThisReference)
{
DataPort strongThisReference= (DataPort)((WeakReference)weakThisReference).Target;
//Extract the things we need from the parameter passed in (the DataPort)
ManualResetEvent dataReady = strongThisReferencedataReady;
WaitHandle closeSignal = strongThisReference.closeSignal;
strongThisReference= null; //Forget the reference to the DataPort.
for(;;)
{
//Same as before, but without "this" . . .
}
}
Now we're OK. The ThreadHelper that gets created holds onto a WeakReference, which won't affect garbage collection. We extract only the data we need from the DataPort at the beginning of the worker thread and then intentionally lose all references to the DataPort. This is OK in this application because the parts of it that we grab don't change over the lifetime of the DataPort. Now, when the top level application loses all references to the DataPort, it's eligible for garbage collection. The GC will run the finalizer which will call the Dispose method which will kill the worker thread. Everything is happy.
However, this is a real pain to do (or at least get right)! Is there a better way to make an object that owns a thread with the same lifetime as that object? Alternatively, is there a way to do this without the thread?
Epilogue:
It would be great if instead of having a thread that spends most of its time doing WaitHandle.WaitAny(), you could have some sort of wait handle that didn't need it's own thread, but would fire a continuation on a Threadpool thread once it's triggered. Like, if the hardware DLL could just call a delegate every time there's new data instead of signaling an event, but I don't control that dll.
I believe that the problem is not in the code you have shown but in the code using this serial port wrapper class. If you don't have a "using" statement there, see http://msdn.microsoft.com/en-us/library/yh598w02.aspx, you don't have deterministic cleanup behaviour. Instead, you then rely on the garbage collector but that will never reap an object that is still referenced, and all stack-variables of a thread (whether as normal parameter or this-pointer) count as references.
Related
Why I see "Hello" words many times when I add timer.Dispose() to my code in release mode. Without timer.Dispose() I see "Hello" once. Thanks.
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Method(object state)
{
Console.WriteLine(state);
GC.Collect();
}
static void Main()
{
var timer = new Timer(Method, "Hello", 0, 200);
Console.ReadLine();
timer.Dispose();
}
}
}
You see it once because the garbage collector has collected the timer object.
Since there are no more references to it that is considered "live" the garbage collector is free to do so.
In release mode, and when no debugger is attached, the JITter builds up knowledge of where local variables are used in a method. Once a variable is no longer used, it is no longer considered to be a root if the method is currently executing below that point. As such, the garbage collector can collect the timer object. However, before it can do so it must finalize the object, which destroys the underlying timer object and stops it from executing.
In debug builds, the scope of all local variables are artificially extended to be the entire method, so that if you place a breakpoint in the method you can inspect variables, even if the program would no longer actually require that variable to exist.
When you added the call to dispose, you extended the lifetime of the variable, and thus prevented the garbage collector from collecting your timer object.
Since you provoke a garbage collection in the timer event handler method, you effectively destroy the timer yourself in this case. When you extended the lifetime of the variable by adding in the call to Dispose, the garbage collector still runs as part of your timer event handler, but it cannot yet collect the timer, so it keeps running.
The answer left here by Hans Passant describes this much better than my meager attempt above:
Understanding Garbage Collection in .NET.
I suspect it's because GC.Collect will not collect the timer object when it's still referenced below the current line of code.
timer.Dispose(); is acting like GC.KeepAlive(timer); in this instance.
If you remove both the Dispose and the GC.Collect(), you will get a few "Hello"s, and then the GC will decide to collect by itself, and you'll get no more.
I have:
public static Thread MainThread
{
get { return Thread.CurrentThread; }
}
in my "main" class
I want to do following in other class:
~Class()
{
Program.MainThread.Start(this.Dispose(false));
}
How can I run method in some thread? How can I run GC in main thread?
How can I run CG in main thread?
GC always runs in it's own threads.
How can I run method in some thread?
You can not unless the other thread has an API entry point waiting for things to process (like the UI has where you can invoke into the message pump).
You can't run a method in the thread remotly.
As for GC, so it can work async, it will run in a different thread.
You can't tell the Garbage Collector when to finalize an object or what thread to finalize an object on.
You can tell the Garbage Collector that now would be a good time to collect by calling GC.Collect.
You can tell the Garbage Collector that an object that fully and properly implements IDisposable, does not need to be finalized by calling GC.SuppressFinalize when IDisposable.Dispose is called directly.
Once again, you cannot control when, other than suppressing, or on what thread that an objects finalizer will be run.
Your Finalizer/Destructor and protected Dispose(bool disposing) implementation have to be aware of this limitation and handle cross-thread and null checks appropriately.
What happens if I call Dispose() on locked object?
lock (obj)
{
obj.Dispose();
}
And what happens if I skip Monitor.Exit() call in this case:
Monitor.Enter(obj);
obj.Dispose();
Implementations of Dispose are not generally thread-safe.
This is because you should not dispose of an object while there are still references which may be used. This implies you should not dispose of an object which any other thread holds a reference to.
IDisposable/Dispose is not a method of managing object lifetime, either in general or across threads - it is a paradigm for releasing the object's resources once its lifetime is over. (The using statement is an idiom/paradigm for use where the object's proper lifetime is the scope of the statement.)
So if you are calling dispose while another thread has the object locked, something has already gone very wrong.
What happens if I call Dispose() on locked object?
First, the object itself is not locked (protected) to begin with. The reference used in the lock keyword is used to mark or tag a section of the code that should not run simultaneously with any other (or same) section of code that used the same object reference. It does not actually affect the object itself. This is a pretty common misconception about how locks work in .NET.
In this context calling Dispose is no different than calling any other method. There is nothing special that happens. It just means that two different threads cannot be executing Dispose simultaneously. What you are doing is not only acceptable, but is actually recommend if the class is not thread-safe.
And what happens if I skip Monitor.Exit() call in this case:
You should always release locks. Keeping in mind that locks do not act upon the object reference itself it should be easier to understand that you would be leaving a lock in an acquired state. It does not matter that the object is disposed. Remember, Monitor (or lock) does not lock or protect the object itself. It only marks or tags a section of code. If a thread attempts to acquire a lock with the same object again then that thread will be forced to wait indefinitely possibly resulting in a deadlock.
A more interesting question is whether this could lead to a memory leak. Does Monitor.Enter root the object? The answer is no. This can be demonstrated with the following example.
public class Program
{
public static void Main(string[] args)
{
var foo = new Foo();
Monitor.Enter(foo);
foo = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadLine();
}
}
internal class Foo
{
~Foo()
{
Console.WriteLine("~Foo");
}
}
If you compile and run this you will observe that "~Foo" is printed out. This suggests that Monitor.Enter does not hold a reference internally. So while it is not advisable to skip the Monitor.Exit call you can have some comfort in knowing that it is not going to cause a memory leak.1
1Actually, this may not be entirely true. While it is fairly easy to demonstrate that there is no managed memory leak things might be different in the unmanaged realm. Short of looking at the SSCLI code we really do not know what Monitor.Enter is doing internally. Maybe it is allocating one additional array slot (or whatever) in the unmanaged heap or stack. I would like to think Microsoft considered this obscure scenario, but who knows. The point is that Monitor.Enter and Monitor.Exit calls should always be paired so that you do not have to worry about it.
The Dispose paradigm is distinct from the lock one. You can safely dispose an object on which you currently hold a mutual-exclusion lock; however, you should still release the lock afterwards. If you fail to do this, other threads that call Monitor.Enter on the (now disposed) object would block indefinitely.
You can always lock on a existing object, The Dispose method won't delete your object, so the object's reference still exists. The Dispose() method isn't affecting the instance of the object.
For your first question - what happens is that only one threat at any given moment may call Dispose().
For your second question - if multiple threads run this code, the 1st one of them will invoke the Dispose method. The rest will block forever.
There is nothing special in the dispose method. It is just like any other method, except that it participates in some syntactic sugar (using statements, for example).
I have a C# application code in which I use a mutex to synchronise some code during the creation of an object. The object constructor acquires the mutex and ONLY releases it when the object is no longer needed (during app shutdown). Thus one place to release the mutex would be in the object destructor. The problem that arose is that sometimes I got an exception during the call to ReleaseMutex() in the object destructor. The exception is: "Object synchronization method was called from an unsynchronized block of code". It appears that the thread that does gabage collection which calls the object destructor sometimes is not the same thread that waits for the mutex (Mutex.WaitOne(false, namedMutex)) in the first place. How do I syncrhonize the acquire and release of the mutex on the same thread to avert this exception? Thanks for your help!
public class MyObject
{
static ExtDeviceDriver devDrv;
private Mutex mut = new Mutex(false,myMutex);
public MyObject()
{
mut.WaitOne();
//Thread safe code here.
devDrv = new ExtDeviceDriver();
}
~MyObject()
{
mut.ReleaseMutex();
}
}
Why don't you use the Dispose pattern? Mutex inherits from WaitHandle and WaitHandle implements IDisposable. If you have a class that creates and uses an IDisposable it should also implement IDisposable and properly be disposed of. Don't let the GC dispose of your mutex for you, manually do it in a using block or manually call .Dispose() on it. This way you can always know who is doing what and when.
This post has a great quote that you should take to heart:
If the object implements IDisposable then you should think about how the object is getting cleaned up.
Objects that implement IDisposable usually do so because they are holding on to real resources that should be freed deterministically.
Which is exactly what is happening here.
Also I see you are using a named mutex. Named mutexes are used across processes and are managed as operating system handles. Is anyone else acquiring the same mutex and trying to release it? Is there a reason you need a named mutex? These are usually tricky to deal with because you can have abandanded mutexes and all sorts of other weird stuff if the process dies and the mutex isn't gracefully handled.
I have the following code (cut down for readability):
Main Class:
public StartProcess()
{
Thinker th = new Thinker();
th.DoneThinking += new Thinker.ProcessingFinished(ThinkerFinished);
th.StartThinking();
}
void ThinkerFinished()
{
Console.WriteLine("Thinker finished");
}
Thinker Class:
public class Thinker
{
private System.Timers.Timer t;
public delegate void ProcessingFinished();
public event ProcessingFinished DoneThinking;
BackgroundWorker backgroundThread;
public Thinker() { }
public StartThinking()
{
t = new System.Timers.Timer(5000); // 5 second timer
t.AutoReset = false;
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
// start a background thread to do the thinking
backgroundThread = new BackgroundWorker();
backgroundThread.DoWork += new DoWorkEventHandler(BgThread_DoWork);
backgroundThread.RunWorkerAsync();
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DoneThinking();
}
BgThread_DoWork(object sender, DoWorkEventArgs e)
{
// work in here should go for much less than 5 seconds
// it will die if it doesn't
t.Stop();
DoneThinking();
}
}
What I originally expected to happen was that the event handler in the main class would prevent the Thinker from being garbage collected.
Apparently this isn't the case.
I'm now wondering whether garbage collection will occur regardless of whether this thread is "busy" or not. In other words, is there a chance it will be garbage collected before the 5 second timeout has expired?
To put it another way, is it possible for the garbage collector to collect my Thinker before it's finished processing?
No, a thread is considered live as long as it is referenced, and any thread that is running is considered to be referenced (IIRC a running thread registers its stack as a GC root, and that stack will reference the thread).
That said i'm looking at your example and i don't understand where you believe a thread is being spawned?
No, a running thread's stack acts as a root for GC purposes. That stack will live as long as the Thread is running, so the Thread itself won't be collected as long its running.
Here's an article that mentions (among other things) what the roots are for GC purposes. To save some time, GC roots are global objects, static objects, all reference on all thread stacks, and all CPU registers containing references.
Your question is a little difficult to answer. Like Joel, as far as I can tell, you have nothing on the stack referencing your timer, which itself is the only thing referencing the thread. Given that, one would expect the Thinker instance would be collected.
I was curious about this, and needed a more concrete explanation of what might happen, so I dug into Reflector a bit. As it turns out, System.Timers.Timer ultimately creates a System.Threading.Timer, which internally creates an instance of TimerBase, an internal class. TimerBase derives from CriticalFinalizerObject, which is a system type that ensures that all code in a Constrained Execution Region (CER) will execute before the implementing class is fully finalized and discarded by the GC. TimerBase is also IDisposable, and its dispose method loops and spinwaits until a lock is released. At this point, I started running into external code, so I am not exactly sure how the lock is initialized or released.
However, based on how the TimerBase class is written, the fact that it derives from CriticalFinalizerObject, and the fact that its dispose spinwaits until a lock is released, I think its safe to say that a thread that is not referenced by anything will not be finalized until that code is done executing. That said...it is important to note that it quite likely will be processed by the GC...quite possibly more than once, as finalization can greatly lengthen the process of collection on finalized objects. For those that are CriticalFinalizerObjects, the finalization process could take even longer if there is actively executing code that the CER is ensuring will fully execute.
That could mean you have exactly the opposite problem if your Thinkers take a while to execute. Rather than those objects being collected prematurely, they will go into a lengthy finalization, and anything they reference ending up in gen2, and living for quite some time until the GC is finally able to fully collect them.
If I'm reading this right (and I could be way off here), it can be collected because it's not currently doing anything.
If you had local variables in your start method, and that method was still active, those variables would still be "in scope" on the stack and provide a root for your thread. But the only variable you use is your private timer, and since that is rooted with the thread itself and the thread has nothing on the stack, there's nothing left to keep it alive.
I agree and disagree, If the reference to the thread object is lost the thread will be terminated and garbage collected. In your case it might not be as such because it is not directly using threads and is using timer. But if you had called a method in a thread and the thread reference was lost with the end of the method then it would be collected by GC