public void AbandonExisting(string name, int waitType) { ThreadTestHelpers.RunTestInBackgroundThread(() => { using (var m = new Mutex(false, name)) { Task t = Task.Factory.StartNew(() => { m.CheckedWait(); // don't release the mutex; abandon it on this thread }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); t.CheckedWait(); switch (waitType) { case 0: // WaitOne Assert.Throws <AbandonedMutexException>(() => m.CheckedWait()); break; case 1: // WaitAny AbandonedMutexException ame = Assert.Throws <AbandonedMutexException>( () => WaitHandle.WaitAny(new[] { m }, ThreadTestHelpers.UnexpectedTimeoutMilliseconds)); Assert.Equal(0, ame.MutexIndex); Assert.Equal(m, ame.Mutex); break; } } }); }
public void WaitTest() { var m = new Mutex(); m.CheckedWait(); m.CheckedWait(); m.ReleaseMutex(); m.ReleaseMutex(); Assert.True(m.WaitOne()); Assert.True(m.WaitOne()); m.ReleaseMutex(); m.ReleaseMutex(); }
public void OpenExisting() { string name = Guid.NewGuid().ToString("N"); Mutex resultHandle; Assert.False(Mutex.TryOpenExisting(name, out resultHandle)); using (Mutex m1 = new Mutex(false, name)) { using (Mutex m2 = Mutex.OpenExisting(name)) { m1.CheckedWait(); Assert.False(Task.Factory.StartNew(() => m2.WaitOne(0), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Result); m1.ReleaseMutex(); m2.CheckedWait(); Assert.False(Task.Factory.StartNew(() => m1.WaitOne(0), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Result); m2.ReleaseMutex(); } Assert.True(Mutex.TryOpenExisting(name, out resultHandle)); Assert.NotNull(resultHandle); resultHandle.Dispose(); } }
public void NamedMutex_ThreadExitDisposeRaceTest() { var mutexName = Guid.NewGuid().ToString("N"); for (int i = 0; i < 1000; ++i) { var m = new Mutex(false, mutexName); var startParallelTest = new ManualResetEvent(false); var t0Ready = new AutoResetEvent(false); Thread t0 = ThreadTestHelpers.CreateGuardedThread(out Action waitForT0, () => { m.CheckedWait(); t0Ready.Set(); startParallelTest.CheckedWait(); // after this, exit T0 }); t0.IsBackground = true; var t1Ready = new AutoResetEvent(false); Thread t1 = ThreadTestHelpers.CreateGuardedThread(out Action waitForT1, () => { using (var m2 = Mutex.OpenExisting(mutexName)) { m.Dispose(); t1Ready.Set(); startParallelTest.CheckedWait(); // after this, close last handle to named mutex, exit T1 } }); t1.IsBackground = true; t0.Start(); t0Ready.CheckedWait(); // wait for T0 to acquire the mutex t1.Start(); t1Ready.CheckedWait(); // wait for T1 to open the existing mutex in a new mutex object and dispose one of the two // Release both threads at the same time. T0 will be exiting the thread, perhaps trying to abandon the mutex // that is still locked by it. In parallel, T1 will be disposing the last mutex instance, which would try to // destroy the mutex. startParallelTest.Set(); waitForT0(); waitForT1(); // Create a new mutex object with the same name and acquire it. There can be a delay between Thread.Join() above // returning and for T0 to abandon its mutex, keep trying to also verify that the mutex object is actually // destroyed and created new again. SpinWait.SpinUntil(() => { using (m = new Mutex(true, mutexName, out bool createdNew)) { if (createdNew) { m.ReleaseMutex(); } return(createdNew); } }); } }
private static void IncrementValueInFileNTimes(Mutex mutex, string fileName, int n) { for (int i = 0; i < n; i++) { mutex.CheckedWait(); try { int current = int.Parse(File.ReadAllText(fileName)); Thread.Sleep(10); File.WriteAllText(fileName, (current + 1).ToString()); } finally { mutex.ReleaseMutex(); } } }
public void CrossProcess_NamedMutex_ProtectedFileAccessAtomic(string prefix) { string fileName = GetTestFilePath(); try { ThreadTestHelpers.RunTestInBackgroundThread(() => { string mutexName = prefix + Guid.NewGuid().ToString("N"); Action <string, string> otherProcess = (m, f) => { using (var mutex = Mutex.OpenExisting(m)) { mutex.CheckedWait(); try { File.WriteAllText(f, "0"); } finally { mutex.ReleaseMutex(); } IncrementValueInFileNTimes(mutex, f, 10); } }; using (var mutex = new Mutex(false, mutexName)) using (var remote = RemoteExecutor.Invoke(otherProcess, mutexName, fileName)) { SpinWait.SpinUntil( () => { mutex.CheckedWait(); try { return(File.Exists(fileName) && int.TryParse(File.ReadAllText(fileName), out _)); } finally { mutex.ReleaseMutex(); } }, ThreadTestHelpers.UnexpectedTimeoutMilliseconds); IncrementValueInFileNTimes(mutex, fileName, 10); } Assert.Equal(20, int.Parse(File.ReadAllText(fileName))); }); } catch (Exception ex) when(File.Exists(fileName)) { throw new AggregateException($"File contents: {File.ReadAllText(fileName)}", ex); } }
public void Ctor_ConstructWaitRelease() { using (Mutex m = new Mutex()) { m.CheckedWait(); m.ReleaseMutex(); } using (Mutex m = new Mutex(false)) { m.CheckedWait(); m.ReleaseMutex(); } using (Mutex m = new Mutex(true)) { m.CheckedWait(); m.ReleaseMutex(); m.ReleaseMutex(); } }
public static void WaitNotificationTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { var tsc = new TestSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(tsc); Assert.Same(tsc, SynchronizationContext.Current); var e = new ManualResetEvent(false); tsc.WaitAction = () => e.Set(); Assert.False(tsc.IsWaitNotificationRequired()); Assert.False(e.WaitOne(0)); tsc.SetWaitNotificationRequired(); Assert.True(tsc.IsWaitNotificationRequired()); Assert.True(e.WaitOne(0)); var mres = new ManualResetEventSlim(); tsc.WaitAction = () => mres.Set(); mres.Reset(); mres.CheckedWait(); e.Reset(); tsc.WaitAction = () => e.Set(); SynchronizationContext.SetSynchronizationContext(new TestSynchronizationContext()); Assert.False(e.WaitOne(0)); SynchronizationContext.SetSynchronizationContext(tsc); Assert.True(e.WaitOne(0)); e.Reset(); e.CheckedWait(); e.Reset(); var lockObj = new object(); var lockAcquiredFromBackground = new AutoResetEvent(false); Action waitForThread; Thread t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { lock (lockObj) { lockAcquiredFromBackground.Set(); e.CheckedWait(); } }); t.IsBackground = true; t.Start(); lockAcquiredFromBackground.CheckedWait(); Assert.True(Monitor.TryEnter(lockObj, ThreadTestHelpers.UnexpectedTimeoutMilliseconds)); Monitor.Exit(lockObj); waitForThread(); e.Reset(); var m = new Mutex(); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { m.CheckedWait(); try { lockAcquiredFromBackground.Set(); e.CheckedWait(); } finally { m.ReleaseMutex(); } }); t.IsBackground = true; t.Start(); lockAcquiredFromBackground.CheckedWait(); m.CheckedWait(); m.ReleaseMutex(); waitForThread(); }); }