Skip to content

Commit

Permalink
Add test for leaking JoinableTask via ExecutionContext
Browse files Browse the repository at this point in the history
  • Loading branch information
AArnott committed Aug 13, 2018
1 parent 6c78ded commit a6f8368
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/Microsoft.VisualStudio.Threading.Tests/JoinableTaskTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3606,6 +3606,24 @@ await Task.Run(async delegate
});
}

[Fact]
public void ExecutionContext_DoesNotLeakJoinableTask()
{
var longLivedTaskReleaser = new AsyncManualResetEvent();
WeakReference weakValue = this.ExecutionContext_DoesNotLeakJoinableTask_Helper(longLivedTaskReleaser);
try
{
// Assert that since no one wants the JoinableTask or its result any more, it has been released.
GC.Collect();
Assert.False(weakValue.IsAlive);
}
finally
{
// Allow completion of our long-lived task.
longLivedTaskReleaser.Set();
}
}

protected override JoinableTaskContext CreateJoinableTaskContext()
{
return new DerivedJoinableTaskContext();
Expand Down Expand Up @@ -3738,6 +3756,32 @@ private void PrintActiveTasksReport(JoinableTaskContext context = null)
this.Logger.WriteLine(report.Content);
}

[MethodImpl(MethodImplOptions.NoInlining)] // must not be inlined so that locals are guaranteed to be freed.
private WeakReference ExecutionContext_DoesNotLeakJoinableTask_Helper(AsyncManualResetEvent releaser)
{
object leakedValue = new object();
WeakReference weakValue = new WeakReference(leakedValue);
Task longLivedTask = null;

this.asyncPump.RunAsync(delegate
{
// Spin off a task that will "capture" the current running JoinableTask
longLivedTask = Task.Factory.StartNew(
async r =>
{
await ((AsyncManualResetEvent)r).WaitAsync();
},
releaser,
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default).Unwrap();

return Task.FromResult(leakedValue);
});

return weakValue;
}

/// <summary>
/// Simulates COM message pump reentrancy causing some unrelated work to "pump in" on top of a synchronously blocking wait.
/// </summary>
Expand Down

0 comments on commit a6f8368

Please sign in to comment.