From 2d16546be98efed43e436790273cf4dde736cbaf Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Mon, 11 Dec 2006 20:11:41 +0000 Subject: [PATCH 1/1] 2006-03-19 Robert Jordan * 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 | 5 ++++ mcs/class/System/System.Timers/Timer.cs | 30 ++++++++++++++++-------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/mcs/class/System/System.Timers/ChangeLog b/mcs/class/System/System.Timers/ChangeLog index 0569399c8f2..1062da725c2 100644 --- a/mcs/class/System/System.Timers/ChangeLog +++ b/mcs/class/System/System.Timers/ChangeLog @@ -1,3 +1,8 @@ +2006-03-19 Robert Jordan + + * Timer.cs: Fix race condition of the wait handle object. + Fixes bug #77847. + 2005-11-16 Sebastien Pouliot * TimersDescriptionAttribute.cs: Revert Description property fix diff --git a/mcs/class/System/System.Timers/Timer.cs b/mcs/class/System/System.Timers/Timer.cs index dc07110bd61..075bcdb2003 100644 --- a/mcs/class/System/System.Timers/Timer.cs +++ b/mcs/class/System/System.Timers/Timer.cs @@ -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 (); } } } -- 2.25.1