Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 54f98dd

Browse files
committed
Merge pull request #2830 from stephentoub/threading_deadlock_tests
Avoid test deadlocks in threading WaitHandle tests
2 parents 08512d6 + 9f48bd2 commit 54f98dd

File tree

4 files changed

+42
-22
lines changed

4 files changed

+42
-22
lines changed

src/System.Threading/tests/AutoResetEventTests.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
public class AutoResetEventTests
1010
{
11+
private const int FailedWaitTimeout = 30000;
12+
1113
[Fact]
1214
public void Ctor()
1315
{
@@ -40,7 +42,7 @@ public void WaitHandleWaitAll()
4042
for (int i = 0; i < handles.Length; i++)
4143
handles[i] = new AutoResetEvent(false);
4244

43-
Task<bool> t = Task.Run(() => WaitHandle.WaitAll(handles));
45+
Task<bool> t = Task.Run(() => WaitHandle.WaitAll(handles, FailedWaitTimeout));
4446
for (int i = 0; i < handles.Length; i++)
4547
{
4648
Assert.False(t.IsCompleted);
@@ -58,7 +60,7 @@ public void WaitHandleWaitAny()
5860
for (int i = 0; i < handles.Length; i++)
5961
handles[i] = new AutoResetEvent(false);
6062

61-
Task<int> t = Task.Run(() => WaitHandle.WaitAny(handles));
63+
Task<int> t = Task.Run(() => WaitHandle.WaitAny(handles, FailedWaitTimeout));
6264
handles[5].Set();
6365
Assert.Equal(5, t.Result);
6466

@@ -76,15 +78,15 @@ public void PingPong()
7678
{
7779
for (int i = 0; i < Iters; i++)
7880
{
79-
Assert.True(are1.WaitOne());
81+
Assert.True(are1.WaitOne(FailedWaitTimeout));
8082
are2.Set();
8183
}
8284
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default),
8385
Task.Factory.StartNew(() =>
8486
{
8587
for (int i = 0; i < Iters; i++)
8688
{
87-
Assert.True(are2.WaitOne());
89+
Assert.True(are2.WaitOne(FailedWaitTimeout));
8890
are1.Set();
8991
}
9092
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default));

src/System.Threading/tests/ManualResetEventTests.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
public class ManualResetEventTests
1010
{
11+
private const int FailedWaitTimeout = 30000;
12+
1113
[Fact]
1214
public void Ctor()
1315
{
@@ -41,7 +43,7 @@ public void WaitHandleWaitAll()
4143
for (int i = 0; i < handles.Length; i++)
4244
handles[i] = new ManualResetEvent(false);
4345

44-
Task<bool> t = Task.Run(() => WaitHandle.WaitAll(handles));
46+
Task<bool> t = Task.Run(() => WaitHandle.WaitAll(handles, FailedWaitTimeout));
4547
for (int i = 0; i < handles.Length; i++)
4648
{
4749
Assert.False(t.IsCompleted);
@@ -59,7 +61,7 @@ public void WaitHandleWaitAny()
5961
for (int i = 0; i < handles.Length; i++)
6062
handles[i] = new ManualResetEvent(false);
6163

62-
Task<int> t = Task.Run(() => WaitHandle.WaitAny(handles));
64+
Task<int> t = Task.Run(() => WaitHandle.WaitAny(handles, FailedWaitTimeout));
6365
handles[5].Set();
6466
Assert.Equal(5, t.Result);
6567

@@ -77,7 +79,7 @@ public void PingPong()
7779
{
7880
for (int i = 0; i < Iters; i++)
7981
{
80-
Assert.True(mre1.WaitOne());
82+
Assert.True(mre1.WaitOne(FailedWaitTimeout));
8183
mre1.Reset();
8284
mre2.Set();
8385
}
@@ -86,7 +88,7 @@ public void PingPong()
8688
{
8789
for (int i = 0; i < Iters; i++)
8890
{
89-
Assert.True(mre2.WaitOne());
91+
Assert.True(mre2.WaitOne(FailedWaitTimeout));
9092
mre2.Reset();
9193
mre1.Set();
9294
}

src/System.Threading/tests/MutexTests.cs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,26 @@
88

99
public class MutexTests
1010
{
11+
private const int FailedWaitTimeout = 30000;
12+
1113
[Fact]
1214
public void Ctor_ConstructWaitRelease()
1315
{
1416
using (Mutex m = new Mutex())
1517
{
16-
Assert.True(m.WaitOne());
18+
Assert.True(m.WaitOne(FailedWaitTimeout));
1719
m.ReleaseMutex();
1820
}
1921

2022
using (Mutex m = new Mutex(false))
2123
{
22-
Assert.True(m.WaitOne());
24+
Assert.True(m.WaitOne(FailedWaitTimeout));
2325
m.ReleaseMutex();
2426
}
2527

2628
using (Mutex m = new Mutex(true))
2729
{
28-
Assert.True(m.WaitOne());
30+
Assert.True(m.WaitOne(FailedWaitTimeout));
2931
m.ReleaseMutex();
3032
m.ReleaseMutex();
3133
}
@@ -86,11 +88,11 @@ public void OpenExisting_Windows()
8688
{
8789
using (Mutex m2 = Mutex.OpenExisting(name))
8890
{
89-
Assert.True(m1.WaitOne());
91+
Assert.True(m1.WaitOne(FailedWaitTimeout));
9092
Assert.False(Task.Factory.StartNew(() => m2.WaitOne(0), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Result);
9193
m1.ReleaseMutex();
9294

93-
Assert.True(m2.WaitOne());
95+
Assert.True(m2.WaitOne(FailedWaitTimeout));
9496
Assert.False(Task.Factory.StartNew(() => m1.WaitOne(0), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Result);
9597
m2.ReleaseMutex();
9698
}
@@ -106,14 +108,23 @@ public void AbandonExisting()
106108
{
107109
using (Mutex m = new Mutex())
108110
{
109-
Task.Factory.StartNew(() => m.WaitOne(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Wait();
110-
Assert.Throws<AbandonedMutexException>(() => m.WaitOne());
111+
Task t = Task.Factory.StartNew(() =>
112+
{
113+
Assert.True(m.WaitOne(FailedWaitTimeout));
114+
// don't release the mutex; abandon it on this thread
115+
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
116+
t.Wait();
117+
Assert.Throws<AbandonedMutexException>(() => m.WaitOne(FailedWaitTimeout));
111118
}
112119

113120
using (Mutex m = new Mutex())
114121
{
115-
Task.Factory.StartNew(() => m.WaitOne(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Wait();
116-
AbandonedMutexException ame = Assert.Throws<AbandonedMutexException>(() => WaitHandle.WaitAny(new[] { m }));
122+
Task t = Task.Factory.StartNew(() =>
123+
{
124+
Assert.True(m.WaitOne(FailedWaitTimeout));
125+
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
126+
t.Wait();
127+
AbandonedMutexException ame = Assert.Throws<AbandonedMutexException>(() => WaitHandle.WaitAny(new[] { m }, FailedWaitTimeout));
117128
Assert.Equal(0, ame.MutexIndex);
118129
}
119130
}

src/System.Threading/tests/SemaphoreTests.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ namespace Test
1010
{
1111
public class SemaphoreTests
1212
{
13+
private const int FailedWaitTimeout = 30000;
14+
1315
[Theory]
1416
[InlineData(0, 1)]
1517
[InlineData(1, 1)]
@@ -154,7 +156,7 @@ public void AnonymousProducerConsumer()
154156
Task.Factory.StartNew(() =>
155157
{
156158
for (int i = 0; i < NumItems; i++)
157-
s.WaitOne();
159+
Assert.True(s.WaitOne(FailedWaitTimeout));
158160
Assert.False(s.WaitOne(0));
159161
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default),
160162
Task.Factory.StartNew(() =>
@@ -169,22 +171,25 @@ public void AnonymousProducerConsumer()
169171
[Fact]
170172
public void NamedProducerConsumer()
171173
{
172-
const string Name = "NamedProducerConsumerSemaphoreTest";
174+
string name = Guid.NewGuid().ToString("N");
173175
const int NumItems = 5;
176+
var b = new Barrier(2);
174177
Task.WaitAll(
175178
Task.Factory.StartNew(() =>
176179
{
177-
using (Semaphore s = new Semaphore(0, Int32.MaxValue, Name))
180+
using (var s = new Semaphore(0, int.MaxValue, name))
178181
{
182+
Assert.True(b.SignalAndWait(FailedWaitTimeout));
179183
for (int i = 0; i < NumItems; i++)
180-
s.WaitOne();
184+
Assert.True(s.WaitOne(FailedWaitTimeout));
181185
Assert.False(s.WaitOne(0));
182186
}
183187
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default),
184188
Task.Factory.StartNew(() =>
185189
{
186-
using (Semaphore s = new Semaphore(0, Int32.MaxValue, Name))
190+
using (var s = new Semaphore(0, int.MaxValue, name))
187191
{
192+
Assert.True(b.SignalAndWait(FailedWaitTimeout));
188193
for (int i = 0; i < NumItems; i++)
189194
s.Release();
190195
}

0 commit comments

Comments
 (0)