Clear unnecessary state from completed Tasks (#20294)
authorStephen Toub <stoub@microsoft.com>
Tue, 9 Oct 2018 17:44:12 +0000 (13:44 -0400)
committerGitHub <noreply@github.com>
Tue, 9 Oct 2018 17:44:12 +0000 (13:44 -0400)
commit39ab08433d9506a338f7e86e723e4d26b95430a1
treea584dd04b8b7b34854a4e2e34d6f966ea59970c6
parentfe00e42185494bb7f27590909d5013b3fc3bbfa7
Clear unnecessary state from completed Tasks (#20294)

When Tasks backed by delegates are created, an ExecutionContext is captured.  When the task completes, its delegate is being cleared, but its ExecutionContext is not, which means if the Task is subsequently kept alive (e.g. stored in a cache), so too is its ExecutionContext, which can capture an arbitrary amount of ambient state via async locals.  This commit augments the clearing of the delegate to similarly clear the ExecutionContext.

Related, async methods can also capture ExecutionContext when awaits yield, so this clears out that context as well.  And as long as we're doing that, we may as well also clear the state machine state, so that any hoisted locals in the state machine aren't kept alive if the resulting task is kept alive.  Not doing so previously was a conscious choice, in order to aid in debugging, but as we've heard of at least a couple of cases where it unexpectedly caused a leak, I'm going ahead and changing it.
src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs