[Mono-bugs] [Bug 47232][Maj] New - Finalizers never called in multi-threaded applications
bugzilla-daemon@rocky.ximian.com
bugzilla-daemon@rocky.ximian.com
Fri, 1 Aug 2003 05:50:59 -0400 (EDT)
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by giuseppe.greco@agamura.com.
http://bugzilla.ximian.com/show_bug.cgi?id=47232
--- shadow/47232 Fri Aug 1 05:50:59 2003
+++ shadow/47232.tmp.15221 Fri Aug 1 05:50:59 2003
@@ -0,0 +1,137 @@
+Bug#: 47232
+Product: Mono/Runtime
+Version: unspecified
+OS: Red Hat 9.0
+OS Details:
+Status: NEW
+Resolution:
+Severity:
+Priority: Major
+Component: misc
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: giuseppe.greco@agamura.com
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Summary: Finalizers never called in multi-threaded applications
+
+Description of Problem:
+
+If a class owns a worker thread, the finalizer is never called,
+and the application just exits brutally.
+
+If you compile the same code after commenting out the code for
+creating the working thread, then the finalizer is called and
+the application exits gracefully.
+
+
+Steps to reproduce the problem:
+
+1. Write a small application like this:
+
+using System;
+using System.Threading;
+
+
+public class MyFinalizer : IDisposable
+{
+ Thread thread;
+ bool isDisposed = false;
+
+
+ public MyFinalizer()
+ {
+ Console.WriteLine("Constructor");
+
+
+ thread = new Thread(new ThreadStart(DoSomething));
+ thread.Start();
+ thread.IsBackground = true;
+ }
+
+
+ private void DoSomething()
+ {
+ while (!isDisposed) {
+ Thread.Sleep(5000);
+ }
+ }
+
+
+ ~MyFinalizer()
+ {
+ Console.WriteLine("Destructor");
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!isDisposed) {
+ Console.WriteLine("Free unmanaged resources.");
+
+
+ //
+ // wait until the working thread completes
+ // its job...
+ //
+ thread.Join();
+
+ if (disposing) {
+ Console.WriteLine("Finalize will be suppressed.");
+ Console.WriteLine("Free resource manually.");
+ }
+
+
+ isDisposed = true;
+ }
+ }
+
+
+ public static void Main()
+ {
+ MyFinalizer f = new MyFinalizer();
+ Console.WriteLine("Bye!");
+ }
+}
+
+2. Compile it:
+
+mcs -t:exe -out:finalizer.exe *.cs
+
+3. Execute it:
+
+mono ./finalizer.exe
+
+
+Actual Results:
+
+The destructor (or finalizer) is never called and the
+working thread is interrupted brutally.
+
+
+Expected Results:
+
+The destructor should be called, which in turn calls
+the Dispose() method. Dispose() allows the application
+to exit gracefully by waiting until the working thread
+completes its job - Thread.Join().
+How often does this happen?
+
+
+Additional Information:
+
+If you comment out the following lines
+
+ // thread = new Thread(new ThreadStart(DoSomething));
+ // thread.Start();
+ // thread.IsBackground = true;
+
+then the finalizer is called and the dispose pattern works
+fine.