2006-03-19 Robert Jordan <robertj@gmx.net>
authorRobert Jordan <robertj@gmx.net>
Mon, 11 Dec 2006 20:11:41 +0000 (20:11 -0000)
committerRobert Jordan <robertj@gmx.net>
Mon, 11 Dec 2006 20:11:41 +0000 (20:11 -0000)
* Timer.cs: Fix race condition of the wait handle object.
Fixes bug #77847.

svn path=/trunk/mcs/; revision=69357

mcs/class/System/System.Timers/ChangeLog
mcs/class/System/System.Timers/Timer.cs

index 0569399c8f2515c2bbb610b03e334ac3aab2e292..1062da725c2d4d3056e003d3bd39f841db577a76 100644 (file)
@@ -1,3 +1,8 @@
+2006-03-19  Robert Jordan  <robertj@gmx.net>
+
+       * Timer.cs: Fix race condition of the wait handle object.
+       Fixes bug #77847.
+
 2005-11-16  Sebastien Pouliot  <sebastien@ximian.com> 
  
        * TimersDescriptionAttribute.cs: Revert Description property fix 
index dc07110bd61858cfb6a98cad1e5ba09786f694bf..075bcdb20034b10c72e7bdd5faf71225fd92a1c6 100644 (file)
@@ -44,6 +44,8 @@ namespace System.Timers
                double interval;
                ISynchronizeInvoke so;
                ManualResetEvent wait;
+               Thread thread;
+               object locker = new object ();
 
                [Category("Behavior")]
                [TimersDescription("Occurs when the Interval has elapsed.")]
@@ -84,9 +86,10 @@ namespace System.Timers
 
                                enabled = value;
                                if (value) {
-                                       Thread t = new Thread (new ThreadStart (StartTimer));
-                                       t.IsBackground = true;
-                                       t.Start ();
+                                       wait = new ManualResetEvent (false);
+                                       thread = new Thread (new ThreadStart (StartTimer));
+                                       thread.IsBackground = true;
+                                       thread.Start ();
                                } else {
                                        StopTimer ();
                                }
@@ -175,8 +178,6 @@ namespace System.Timers
 
                void StartTimer ()
                {
-                       wait = new ManualResetEvent (false);
-
                        WaitCallback wc = new WaitCallback (Callback);
                        while (enabled && wait.WaitOne ((int) interval, false) == false) {
                                if (autoReset == false)
@@ -184,16 +185,25 @@ namespace System.Timers
 
                                ThreadPool.QueueUserWorkItem (wc, this);
                        }
-                       
+
                        wc = null;
-                       ((IDisposable) wait).Dispose ();
-                       wait = null;
+
+                       lock (locker) {
+                               ((IDisposable) wait).Dispose ();
+                               wait = null;
+                       }
                }
 
                void StopTimer ()
                {
-                       if (wait != null)
-                               wait.Set ();
+                       lock (locker) {
+                               if (wait != null)
+                                       wait.Set ();
+                       }
+
+                       // the sleep speeds up the join under linux
+                       Thread.Sleep (0);
+                       thread.Join ();
                }
        }
 }