From a47707dbf410600d30fa07a86620eea6fbc2dc64 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 13 Aug 2024 14:39:36 -0600 Subject: [PATCH] Fix `JoinableTaskContext.serializedTasks` leak The collection of joinable tasks for which an ID is requested grew forever. The code that should purge completed tasks from the collection was never executing because the `TaskId` property is programmed to return `null` for completed tasks, and we query the property directly *after* setting the task as completed. The fix then is simple: fetch the TaskId value *first* and *then* set the `JoinableTask` as completed. --- src/Microsoft.VisualStudio.Threading/JoinableTask.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.VisualStudio.Threading/JoinableTask.cs b/src/Microsoft.VisualStudio.Threading/JoinableTask.cs index 703c35323..bf214e123 100644 --- a/src/Microsoft.VisualStudio.Threading/JoinableTask.cs +++ b/src/Microsoft.VisualStudio.Threading/JoinableTask.cs @@ -927,10 +927,14 @@ internal void Complete(Task wrappedTask) { if (!this.IsCompleteRequested) { + // This must be done *before* setting IsCompleteRequested so that the TaskId property will still return the value we need. + ulong? taskId = this.token?.TaskId; + this.IsCompleteRequested = true; - if (this.token?.TaskId is ulong taskId) + + if (taskId.HasValue) { - this.JoinableTaskContext.RemoveSerializableIdentifier(taskId); + this.JoinableTaskContext.RemoveSerializableIdentifier(taskId.Value); } if (this.mainThreadQueue is object)