Skip to content

Fix memory leak with IOptionsMonitor.OnChange and non-singleton registered components (closes #20709 for 16/17)#20723

Merged
AndyButland merged 6 commits intomainfrom
v17/bugfix/handle-options-monitor-memory-leak
Nov 6, 2025
Merged

Fix memory leak with IOptionsMonitor.OnChange and non-singleton registered components (closes #20709 for 16/17)#20723
AndyButland merged 6 commits intomainfrom
v17/bugfix/handle-options-monitor-memory-leak

Conversation

@AndyButland
Copy link
Contributor

Prerequisites

Addresses #20709

Description

This is the 17 version of #20722 (that I'll also backport to 16 once approved).

As per the other PR, the fixes are either adopting the disposable pattern, or where registered transient, removing the OnChange handler as it's unnecessary if the class isn't long lived.

Copilot AI review requested due to automatic review settings November 4, 2025 08:55
# Conflicts:
#	src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors configuration settings handling across multiple classes by removing dynamic OnChange subscriptions and making settings immutable (readonly). The primary goal is to prevent memory leaks from subscriptions that were never properly disposed.

  • Converted mutable settings fields to readonly fields, capturing configuration values only at construction time
  • Removed OnChange subscription handlers that were updating settings dynamically
  • Added IDisposable implementation to classes that still need subscriptions (value editors and converters)
  • Made fields readonly in classes where subscriptions were completely removed

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
EmailUserForgotPasswordSender.cs Made GlobalSettings and SecuritySettings fields readonly, removed OnChange subscriptions
IndexingNotificationHandler.DeliveryApi.cs Made DeliveryApiSettings field readonly, removed OnChange subscription
RteBlockRenderingValueConverter.cs Made DeliveryApiSettings readonly, stored subscription as IDisposable field, implemented IDisposable
ImageCropperPropertyValueEditor.cs Made ContentSettings readonly, stored subscription as IDisposable field, implemented IDisposable
ImageCropperPropertyEditor.cs Made ContentSettings readonly, stored subscription as IDisposable field, implemented IDisposable, removed null checks
FileUploadPropertyValueEditor.cs Made ContentSettings readonly, stored subscription as IDisposable field, implemented IDisposable, removed null checks
ApiPublishedContentCache.cs Removed unused imports
ModelsBuilderPresentationFactory.cs Made ModelsBuilderSettings field readonly, removed OnChange subscription, cleaned up imports
BuildModelsBuilderController.cs Made ModelsBuilderSettings field readonly, removed OnChange subscription, cleaned up imports
GetHelpController.cs Made HelpPageSettings field readonly, removed OnChange subscription and helper method

Copy link
Contributor

@Migaroez Migaroez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a look over the codebase and can't find any other cases where we can make meaningfull improvments as all other event subscribers are either

  • subclasses of the event publisher: same lifetime
  • the subscribers are DI singletons: they have application lifetime so they cant have a shorter lifetime than the publisher
  • the subscribers are registered into a builderscollection which shouldn't be mutated after the compute phase which makes them equivalent to the previous scenario.

The only thing i would change is to remove the changes to the propertyEditor so the intent of the PR is to only implement changes to things where we see risks in normal operation/implementation.

@AndyButland
Copy link
Contributor Author

The only thing i would change is to remove the changes to the propertyEditor so the intent of the PR is to only implement changes to things where we see risks in normal operation/implementation.

Could you be a bit more specific about what you are suggesting to revert here please?

@AndyButland AndyButland force-pushed the v17/bugfix/handle-options-monitor-memory-leak branch from e0e33c7 to 8ad6b37 Compare November 6, 2025 14:35
@AndyButland AndyButland merged commit 7162c45 into main Nov 6, 2025
25 of 26 checks passed
@AndyButland AndyButland deleted the v17/bugfix/handle-options-monitor-memory-leak branch November 6, 2025 16:16
AndyButland added a commit that referenced this pull request Nov 6, 2025
…istered components (closes #20709 for 16/17) (#20723)

* Fix memory leak with IOptionsMonitor.OnChange and non-singleton registered components.

* Dispose disposable data editors in ValueEditorCache.

* Removed unnecessary refactoring and clarified code comments.
# Conflicts:
#	src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants