[corlib] Fix NullRef when using dispose a CancellationTokenRegistration when the...
authorJeremie Laval <jeremie.laval@gmail.com>
Wed, 16 May 2012 10:50:17 +0000 (11:50 +0100)
committerJeremie Laval <jeremie.laval@gmail.com>
Wed, 16 May 2012 10:50:17 +0000 (11:50 +0100)
mcs/class/corlib/System.Threading/CancellationTokenSource.cs
mcs/class/corlib/Test/System.Threading/CancellationTokenSourceTest.cs

index 4c5b2b2196ca47ae937828aa4ca1193b5766d63b..fa9674e06f1b790ee30f962fd1e1736d350335e7 100644 (file)
@@ -230,6 +230,7 @@ namespace System.Threading
                {
                        if (disposing && !disposed) {
                                disposed = true;
+                               Thread.MemoryBarrier ();
 
                                callbacks = null;
 #if NET_4_5
@@ -263,8 +264,13 @@ namespace System.Threading
 
                internal void RemoveCallback (CancellationTokenRegistration reg)
                {
+                       // Ignore call if the source has been disposed
+                       if (disposed)
+                               return;
                        Action dummy;
-                       callbacks.TryRemove (reg, out dummy);
+                       var cbs = callbacks;
+                       if (cbs != null)
+                               cbs.TryRemove (reg, out dummy);
                }
        }
 }
index e683d33bf1c781d4401c64d0f430aa5e2f641dbb..5d8d855ed2f72fe443f7b82767107ae278a48c1d 100644 (file)
@@ -340,6 +340,17 @@ namespace MonoTests.System.Threading
                        Assert.IsFalse (unregister);
                        Assert.IsTrue (register);
                }
+
+               [Test]
+               public void DisposeAfterRegistrationTest ()
+               {
+                       var source = new CancellationTokenSource ();
+                       bool ran = false;
+                       var req = source.Token.Register (() => ran = true);
+                       source.Dispose ();
+                       req.Dispose ();
+                       Assert.IsFalse (ran);
+               }
        }
 }