Skip to content

Commit 2e98bc0

Browse files
committed
Don't leak ManualResetEventSlims or Threads waiting on them
- related to aspnet#11 (2 of 4 additions) - tests sometimes hang with loads of threads stuck in `BackgroundParser.MainThreadState.GetParcel()`
1 parent 29a8fee commit 2e98bc0

File tree

14 files changed

+938
-813
lines changed

14 files changed

+938
-813
lines changed

test/Microsoft.Web.Mvc.Test/Test/AsyncManagerExtensionsTest.cs

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,31 @@ public void RegisterTask_AsynchronousCompletion()
1818
AsyncManager asyncManager = new AsyncManager(syncContext);
1919
bool endDelegateWasCalled = false;
2020

21-
ManualResetEvent waitHandle = new ManualResetEvent(false /* initialState */);
22-
23-
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
21+
using (ManualResetEvent waitHandle = new ManualResetEvent(false /* initialState */))
2422
{
25-
Assert.Equal(1, asyncManager.OutstandingOperations.Count);
26-
MockAsyncResult asyncResult = new MockAsyncResult(false /* completedSynchronously */);
27-
ThreadPool.QueueUserWorkItem(_ =>
23+
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
2824
{
2925
Assert.Equal(1, asyncManager.OutstandingOperations.Count);
30-
callback(asyncResult);
31-
waitHandle.Set();
32-
});
33-
return asyncResult;
34-
};
35-
Action<IAsyncResult> endDelegate = delegate { endDelegateWasCalled = true; };
36-
37-
// Act
38-
asyncManager.RegisterTask(beginDelegate, endDelegate);
39-
waitHandle.WaitOne();
40-
41-
// Assert
42-
Assert.True(endDelegateWasCalled);
43-
Assert.True(syncContext.SendWasCalled);
44-
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
26+
MockAsyncResult asyncResult = new MockAsyncResult(false /* completedSynchronously */);
27+
ThreadPool.QueueUserWorkItem(_ =>
28+
{
29+
Assert.Equal(1, asyncManager.OutstandingOperations.Count);
30+
callback(asyncResult);
31+
waitHandle.Set();
32+
});
33+
return asyncResult;
34+
};
35+
Action<IAsyncResult> endDelegate = delegate { endDelegateWasCalled = true; };
36+
37+
// Act
38+
asyncManager.RegisterTask(beginDelegate, endDelegate);
39+
waitHandle.WaitOne();
40+
41+
// Assert
42+
Assert.True(endDelegateWasCalled);
43+
Assert.True(syncContext.SendWasCalled);
44+
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
45+
}
4546
}
4647

4748
[Fact]
@@ -52,31 +53,32 @@ public void RegisterTask_AsynchronousCompletion_SwallowsExceptionsThrownByEndDel
5253
AsyncManager asyncManager = new AsyncManager(syncContext);
5354
bool endDelegateWasCalled = false;
5455

55-
ManualResetEvent waitHandle = new ManualResetEvent(false /* initialState */);
56-
57-
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
56+
using (ManualResetEvent waitHandle = new ManualResetEvent(false /* initialState */))
5857
{
59-
MockAsyncResult asyncResult = new MockAsyncResult(false /* completedSynchronously */);
60-
ThreadPool.QueueUserWorkItem(_ =>
58+
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
6159
{
62-
callback(asyncResult);
63-
waitHandle.Set();
64-
});
65-
return asyncResult;
66-
};
67-
Action<IAsyncResult> endDelegate = delegate
68-
{
69-
endDelegateWasCalled = true;
70-
throw new Exception("This is a sample exception.");
71-
};
60+
MockAsyncResult asyncResult = new MockAsyncResult(false /* completedSynchronously */);
61+
ThreadPool.QueueUserWorkItem(_ =>
62+
{
63+
callback(asyncResult);
64+
waitHandle.Set();
65+
});
66+
return asyncResult;
67+
};
68+
Action<IAsyncResult> endDelegate = delegate
69+
{
70+
endDelegateWasCalled = true;
71+
throw new Exception("This is a sample exception.");
72+
};
7273

73-
// Act
74-
asyncManager.RegisterTask(beginDelegate, endDelegate);
75-
waitHandle.WaitOne();
74+
// Act
75+
asyncManager.RegisterTask(beginDelegate, endDelegate);
76+
waitHandle.WaitOne();
7677

77-
// Assert
78-
Assert.True(endDelegateWasCalled);
79-
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
78+
// Assert
79+
Assert.True(endDelegateWasCalled);
80+
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
81+
}
8082
}
8183

8284
[Fact]

test/System.Net.Http.Formatting.Test/Handlers/ProgressStreamTest.cs

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -191,74 +191,78 @@ public void WriteByte_ReportsBytesWritten()
191191
public void BeginEndWrite_ReportsBytesWritten()
192192
{
193193
// Arrange
194-
ManualResetEvent writeComplete = new ManualResetEvent(false);
195-
HttpRequestMessage request = CreateRequest();
196-
Stream innerStream = new MemoryStream();
197-
byte[] buffer = CreateBufferContent();
198-
long? expectedLength = request.Content.Headers.ContentLength;
199-
MockProgressEventHandler mockProgressEventHandler;
200-
ProgressMessageHandler progressMessageHandler = MockProgressEventHandler.CreateProgressMessageHandler(out mockProgressEventHandler, sendProgress: true);
201-
ProgressStream progressStream = CreateProgressStream(innerStream: innerStream, progressMessageHandler: progressMessageHandler, request: request);
202-
object userState = new object();
203-
204-
// Act/Assert
205-
int totalBytesWritten = 0;
206-
int bytesWritten = 0;
207-
while (totalBytesWritten < expectedLength)
194+
using (ManualResetEvent writeComplete = new ManualResetEvent(false))
208195
{
209-
bytesWritten = Math.Min(8, (int)expectedLength - totalBytesWritten);
210-
IAsyncResult result = progressStream.BeginWrite(buffer, totalBytesWritten, bytesWritten,
211-
ia =>
212-
{
213-
progressStream.EndWrite(ia);
214-
writeComplete.Set();
215-
},
216-
userState);
217-
218-
writeComplete.WaitOne();
219-
writeComplete.Reset();
220-
totalBytesWritten += bytesWritten;
221-
222-
Assert.Same(userState, mockProgressEventHandler.EventArgs.UserState);
223-
Assert.Equal(totalBytesWritten, mockProgressEventHandler.EventArgs.BytesTransferred);
224-
Assert.Equal((100L * totalBytesWritten) / expectedLength, mockProgressEventHandler.EventArgs.ProgressPercentage);
196+
HttpRequestMessage request = CreateRequest();
197+
Stream innerStream = new MemoryStream();
198+
byte[] buffer = CreateBufferContent();
199+
long? expectedLength = request.Content.Headers.ContentLength;
200+
MockProgressEventHandler mockProgressEventHandler;
201+
ProgressMessageHandler progressMessageHandler = MockProgressEventHandler.CreateProgressMessageHandler(out mockProgressEventHandler, sendProgress: true);
202+
ProgressStream progressStream = CreateProgressStream(innerStream: innerStream, progressMessageHandler: progressMessageHandler, request: request);
203+
object userState = new object();
204+
205+
// Act/Assert
206+
int totalBytesWritten = 0;
207+
int bytesWritten = 0;
208+
while (totalBytesWritten < expectedLength)
209+
{
210+
bytesWritten = Math.Min(8, (int)expectedLength - totalBytesWritten);
211+
IAsyncResult result = progressStream.BeginWrite(buffer, totalBytesWritten, bytesWritten,
212+
ia =>
213+
{
214+
progressStream.EndWrite(ia);
215+
writeComplete.Set();
216+
},
217+
userState);
218+
219+
writeComplete.WaitOne();
220+
writeComplete.Reset();
221+
totalBytesWritten += bytesWritten;
222+
223+
Assert.Same(userState, mockProgressEventHandler.EventArgs.UserState);
224+
Assert.Equal(totalBytesWritten, mockProgressEventHandler.EventArgs.BytesTransferred);
225+
Assert.Equal((100L * totalBytesWritten) / expectedLength, mockProgressEventHandler.EventArgs.ProgressPercentage);
226+
}
227+
228+
Assert.Equal(expectedLength, mockProgressEventHandler.EventArgs.TotalBytes);
229+
Assert.Equal(100, mockProgressEventHandler.EventArgs.ProgressPercentage);
225230
}
226-
227-
Assert.Equal(expectedLength, mockProgressEventHandler.EventArgs.TotalBytes);
228-
Assert.Equal(100, mockProgressEventHandler.EventArgs.ProgressPercentage);
229231
}
230232
#endif
231233

232234
[Fact]
233235
public async Task WriteAsync_ReportsBytesWritten()
234236
{
235237
// Arrange
236-
ManualResetEvent writeComplete = new ManualResetEvent(false);
237-
HttpRequestMessage request = CreateRequest();
238-
Stream innerStream = new MemoryStream();
239-
byte[] buffer = CreateBufferContent();
240-
long? expectedLength = request.Content.Headers.ContentLength;
241-
MockProgressEventHandler mockProgressEventHandler;
242-
ProgressMessageHandler progressMessageHandler = MockProgressEventHandler.CreateProgressMessageHandler(out mockProgressEventHandler, sendProgress: true);
243-
ProgressStream progressStream = CreateProgressStream(innerStream: innerStream, progressMessageHandler: progressMessageHandler, request: request);
244-
object userState = new object();
245-
246-
// Act/Assert
247-
int totalBytesWritten = 0;
248-
int bytesWritten = 0;
249-
while (totalBytesWritten < expectedLength)
238+
using (ManualResetEvent writeComplete = new ManualResetEvent(false))
250239
{
251-
bytesWritten = Math.Min(8, (int)expectedLength - totalBytesWritten);
252-
await progressStream.WriteAsync(buffer, totalBytesWritten, bytesWritten);
253-
254-
totalBytesWritten += bytesWritten;
255-
256-
Assert.Equal(totalBytesWritten, mockProgressEventHandler.EventArgs.BytesTransferred);
257-
Assert.Equal((100L * totalBytesWritten) / expectedLength, mockProgressEventHandler.EventArgs.ProgressPercentage);
240+
HttpRequestMessage request = CreateRequest();
241+
Stream innerStream = new MemoryStream();
242+
byte[] buffer = CreateBufferContent();
243+
long? expectedLength = request.Content.Headers.ContentLength;
244+
MockProgressEventHandler mockProgressEventHandler;
245+
ProgressMessageHandler progressMessageHandler = MockProgressEventHandler.CreateProgressMessageHandler(out mockProgressEventHandler, sendProgress: true);
246+
ProgressStream progressStream = CreateProgressStream(innerStream: innerStream, progressMessageHandler: progressMessageHandler, request: request);
247+
object userState = new object();
248+
249+
// Act/Assert
250+
int totalBytesWritten = 0;
251+
int bytesWritten = 0;
252+
while (totalBytesWritten < expectedLength)
253+
{
254+
bytesWritten = Math.Min(8, (int)expectedLength - totalBytesWritten);
255+
await progressStream.WriteAsync(buffer, totalBytesWritten, bytesWritten);
256+
257+
totalBytesWritten += bytesWritten;
258+
259+
Assert.Equal(totalBytesWritten, mockProgressEventHandler.EventArgs.BytesTransferred);
260+
Assert.Equal((100L * totalBytesWritten) / expectedLength, mockProgressEventHandler.EventArgs.ProgressPercentage);
261+
}
262+
263+
Assert.Equal(expectedLength, mockProgressEventHandler.EventArgs.TotalBytes);
264+
Assert.Equal(100, mockProgressEventHandler.EventArgs.ProgressPercentage);
258265
}
259-
260-
Assert.Equal(expectedLength, mockProgressEventHandler.EventArgs.TotalBytes);
261-
Assert.Equal(100, mockProgressEventHandler.EventArgs.ProgressPercentage);
262266
}
263267

264268
internal static ProgressStream CreateProgressStream(

0 commit comments

Comments
 (0)