Example #1
0
        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;
                    }
                }
            });
        }
Example #2
0
        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();
        }
Example #3
0
        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();
            }
        }
Example #4
0
        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);
                    }
                });
            }
        }
Example #5
0
 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(); }
     }
 }
Example #6
0
        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);
            }
        }
Example #7
0
        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();
            });
        }
        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();
            });
        }