Пример #1
0
        public void AbandonExisting(
            string name,
            WaitHandleWaitType waitType,
            int waitCount,
            int notAbandonedWaitIndex,
            bool isNotAbandonedWaitObjectSignaled,
            bool abandonDuringWait)
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                using (var m = new Mutex(false, name))
                    using (Mutex m2 = waitCount == 1 ? null : new Mutex(false, name == null ? null : name + "_2"))
                        using (ManualResetEvent e = waitCount == 1 ? null : new ManualResetEvent(isNotAbandonedWaitObjectSignaled))
                            using (ManualResetEvent threadReadyForAbandon = abandonDuringWait ? new ManualResetEvent(false) : null)
                                using (ManualResetEvent abandonSoon = abandonDuringWait ? new ManualResetEvent(false) : null)
                                {
                                    WaitHandle[] waitHandles = null;
                                    if (waitType != WaitHandleWaitType.WaitOne)
                                    {
                                        waitHandles = new WaitHandle[waitCount];
                                        if (waitCount == 1)
                                        {
                                            waitHandles[0] = m;
                                        }
                                        else
                                        {
                                            waitHandles[notAbandonedWaitIndex] = e;
                                            waitHandles[notAbandonedWaitIndex == 0 ? 1 : 0] = m;
                                            waitHandles[notAbandonedWaitIndex == 2 ? 1 : 2] = m2;
                                        }
                                    }

                                    Thread t = ThreadTestHelpers.CreateGuardedThread(out Action waitForThread, () =>
                                    {
                                        Assert.True(m.WaitOne(0));
                                        if (m2 != null)
                                        {
                                            Assert.True(m2.WaitOne(0));
                                        }

                                        if (abandonDuringWait)
                                        {
                                            threadReadyForAbandon.Set();
                                            abandonSoon.CheckedWait();
                                            Thread.Sleep(ThreadTestHelpers.ExpectedTimeoutMilliseconds);
                                        }

                                        // don't release the mutexes; abandon them on this thread
                                    });
                                    t.IsBackground = true;
                                    t.Start();

                                    if (abandonDuringWait)
                                    {
                                        threadReadyForAbandon.CheckedWait();
                                        abandonSoon.Set();
                                    }
                                    else
                                    {
                                        waitForThread();
                                    }

                                    AbandonedMutexException ame;
                                    switch (waitType)
                                    {
                                    case WaitHandleWaitType.WaitOne:
                                        ame =
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        Assert.Equal(-1, ame.MutexIndex);
                                        Assert.Null(ame.Mutex);
                                        break;

                                    case WaitHandleWaitType.WaitAny:
                                        if (waitCount != 1 && isNotAbandonedWaitObjectSignaled && notAbandonedWaitIndex == 0)
                                        {
                                            Assert.Equal(0, WaitHandle.WaitAny(waitHandles, 0));
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m2.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            break;
                                        }

                                        if (waitCount != 1 && isNotAbandonedWaitObjectSignaled && notAbandonedWaitIndex != 0)
                                        {
                                            ame =
                                                Assert.Throws <AbandonedMutexException>(() =>
                                            {
                                                ThreadTestHelpers.WaitForCondition(() =>
                                                {
                                                    // Actually expecting an exception from WaitAny(), but there may be a delay before
                                                    // the mutex is actually released and abandoned. If there is no exception, the
                                                    // WaitAny() must have succeeded due to the event being signaled.
                                                    int r = WaitHandle.WaitAny(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds);
                                                    Assert.Equal(notAbandonedWaitIndex, r);
                                                    return(false);
                                                });
                                            });
                                        }
                                        else
                                        {
                                            ame =
                                                AssertExtensions.Throws <AbandonedMutexException, int>(
                                                    () => WaitHandle.WaitAny(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        }

                                        // Due to a potential delay in abandoning mutexes, either mutex may have been seen to be
                                        // abandoned first
                                        Assert.True(ame.Mutex == m || (m2 != null && ame.Mutex == m2));
                                        int mIndex  = waitCount != 1 && notAbandonedWaitIndex == 0 ? 1 : 0;
                                        int m2Index = waitCount != 1 && notAbandonedWaitIndex == 2 ? 1 : 2;
                                        if (ame.Mutex == m)
                                        {
                                            Assert.Equal(mIndex, ame.MutexIndex);
                                        }
                                        else
                                        {
                                            Assert.True(m2Index < notAbandonedWaitIndex);
                                            Assert.Equal(m2Index, ame.MutexIndex);
                                        }

                                        // Verify that the other mutex also gets abandoned
                                        if (ame.MutexIndex == mIndex)
                                        {
                                            if (m2 != null)
                                            {
                                                AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                    () => m2.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            }
                                        }
                                        else
                                        {
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        }

                                        break;

                                    case WaitHandleWaitType.WaitAll:
                                        if (waitCount != 1 && !isNotAbandonedWaitObjectSignaled)
                                        {
                                            Assert.False(WaitHandle.WaitAll(waitHandles, ThreadTestHelpers.ExpectedTimeoutMilliseconds * 2));
                                            Assert.True(e.Set());
                                        }

                                        ame =
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => WaitHandle.WaitAll(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        Assert.Equal(-1, ame.MutexIndex);
                                        Assert.Null(ame.Mutex);
                                        break;
                                    }

                                    if (abandonDuringWait)
                                    {
                                        waitForThread();
                                    }

                                    m.ReleaseMutex();
                                    m2?.ReleaseMutex();
                                }
            });
        }
Пример #2
0
        public void AbandonExisting(
            string name,
            WaitHandleWaitType waitType,
            int waitCount,
            int notAbandonedWaitIndex,
            bool isNotAbandonedWaitObjectSignaled,
            bool abandonDuringWait)
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                using (var m = new Mutex(false, name))
                    using (Mutex m2 = waitCount == 1 ? null : new Mutex(false, name == null ? null : name + "_2"))
                        using (ManualResetEvent e = waitCount == 1 ? null : new ManualResetEvent(isNotAbandonedWaitObjectSignaled))
                            using (ManualResetEvent threadReadyForAbandon = abandonDuringWait ? new ManualResetEvent(false) : null)
                                using (ManualResetEvent abandonSoon = abandonDuringWait ? new ManualResetEvent(false) : null)
                                {
                                    WaitHandle[] waitHandles = null;
                                    if (waitType != WaitHandleWaitType.WaitOne)
                                    {
                                        waitHandles = new WaitHandle[waitCount];
                                        if (waitCount == 1)
                                        {
                                            waitHandles[0] = m;
                                        }
                                        else
                                        {
                                            waitHandles[notAbandonedWaitIndex] = e;
                                            waitHandles[notAbandonedWaitIndex == 0 ? 1 : 0] = m;
                                            waitHandles[notAbandonedWaitIndex == 2 ? 1 : 2] = m2;
                                        }
                                    }

                                    Thread t = ThreadTestHelpers.CreateGuardedThread(out Action waitForThread, () =>
                                    {
                                        Assert.True(m.WaitOne(0));
                                        if (m2 != null)
                                        {
                                            Assert.True(m2.WaitOne(0));
                                        }

                                        if (abandonDuringWait)
                                        {
                                            threadReadyForAbandon.Set();
                                            abandonSoon.CheckedWait();
                                            Thread.Sleep(ThreadTestHelpers.ExpectedTimeoutMilliseconds);
                                        }

                                        // don't release the mutexes; abandon them on this thread
                                    });
                                    t.IsBackground = true;
                                    t.Start();

                                    if (abandonDuringWait)
                                    {
                                        threadReadyForAbandon.CheckedWait();
                                        abandonSoon.Set();
                                    }
                                    else
                                    {
                                        waitForThread();
                                    }

                                    AbandonedMutexException ame;
                                    switch (waitType)
                                    {
                                    case WaitHandleWaitType.WaitOne:
                                        ame =
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        Assert.Equal(-1, ame.MutexIndex);
                                        Assert.Null(ame.Mutex);
                                        break;

                                    case WaitHandleWaitType.WaitAny:
                                        if (waitCount != 1 && isNotAbandonedWaitObjectSignaled && notAbandonedWaitIndex == 0)
                                        {
                                            Assert.Equal(0, WaitHandle.WaitAny(waitHandles, 0));
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        }
                                        else
                                        {
                                            ame =
                                                AssertExtensions.Throws <AbandonedMutexException, int>(
                                                    () => WaitHandle.WaitAny(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                            Assert.Equal(waitCount != 1 && notAbandonedWaitIndex == 0 ? 1 : 0, ame.MutexIndex);
                                            Assert.Equal(m, ame.Mutex);
                                        }

                                        if (m2 != null)
                                        {
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => m2.WaitOne(ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        }
                                        break;

                                    case WaitHandleWaitType.WaitAll:
                                        if (waitCount != 1 && !isNotAbandonedWaitObjectSignaled)
                                        {
                                            Assert.False(WaitHandle.WaitAll(waitHandles, ThreadTestHelpers.ExpectedTimeoutMilliseconds * 2));
                                            Assert.True(e.Set());
                                        }

                                        ame =
                                            AssertExtensions.Throws <AbandonedMutexException, bool>(
                                                () => WaitHandle.WaitAll(waitHandles, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                                        Assert.Equal(-1, ame.MutexIndex);
                                        Assert.Null(ame.Mutex);
                                        break;
                                    }

                                    if (abandonDuringWait)
                                    {
                                        waitForThread();
                                    }

                                    m.ReleaseMutex();
                                    m2?.ReleaseMutex();
                                }
            });
        }