From 7475c2c6c2df2c0a882a28a0e84606202f3151a8 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 10 Jul 2023 20:05:49 +0000 Subject: [PATCH] [stable] [analyzer] Clear watcher subscriptions to avoid leaking package:watcher data Analyzer adds watchers to all root folders it has opened. When editing, say, a pubspec.yaml file it ~starts over, cancels the old subscriptions and creates new ones. It keeps references to the old subscriptions too though. This in turn leaks data. On Linux internally in package:watcher it clears some stuff as it's cancelled, but it doesn't on Windows, nor on Mac. The means it can leak an infinite amount of `_Entry` classes, and for instance in https://github.com/dart-lang/sdk/issues/52447 a user has 40+ million of those classes. Reproducing this I got to 40+ million too, at which point the "Retained size" of all the `_Entry` objects was 7.39GB. This fixes the leak by clearing the list. Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/308940 Change-Id: I8a4bdbc97259bd8e13209909769330ca6d81b2a5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311466 Commit-Queue: Samuel Rawlins Reviewed-by: Konstantin Shcheglov --- CHANGELOG.md | 2 ++ pkg/analysis_server/lib/src/context_manager.dart | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb26f3b1765..8039136ac792 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,10 @@ This is a patch release that: - Fixes a flow in flow analysis that causes it to sometimes ignore destructuring assignments (issue [#52767]). +- Fixes a memory leak in Dart analyzer's file-watching (issue [#52791]). [#52767]: https://github.com/dart-lang/sdk/issues/52767 +[#52791]: https://github.com/dart-lang/sdk/issues/52791 ## 3.0.5 - 2023-06-14 diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart index 710fbd6b704d..63a1e3412e04 100644 --- a/pkg/analysis_server/lib/src/context_manager.dart +++ b/pkg/analysis_server/lib/src/context_manager.dart @@ -643,11 +643,13 @@ class ContextManagerImpl implements ContextManager { } Future _destroyAnalysisContexts() async { + for (final subscription in watcherSubscriptions) { + await subscription.cancel(); + } + watcherSubscriptions.clear(); + final collection = _collection; if (collection != null) { - for (final subscription in watcherSubscriptions) { - await subscription.cancel(); - } for (final analysisContext in collection.contexts) { _destroyAnalysisContext(analysisContext); }