Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/6.0] Store ApplicationServiceProvider in a WeakReference #27190

Merged
merged 1 commit into from
Feb 2, 2022

Conversation

AndriySvyryd
Copy link
Member

@AndriySvyryd AndriySvyryd commented Jan 14, 2022

Fixes #27169

Description

In 6.0 we made a change to ServiceProviderCache to use instances of IDbContextOptions as keys for the internal ConcurrentDictionary. A key of type IDbContextOptions contains, among other things, the extension CoreOptionsExtension which has an ApplicationServiceProvider reference pointing to the service provider that was used to create the options.

After creation and disposal of the first DbContext the ServiceProviderCache keeps the IDbContextOptions incl. the (disposed) service provider scope, which still references all disposed scoped services, including the DbContext itself.

Customer impact

The first service provider scope per each DbContext type used in the application will never be garbage collected.

How found

Customer reported on 6.0.1

Regression

Yes. Regressed by #25313

Testing

Verified manually.

Risk

Low. This reverts the behavior to 5.0 wrt referencing ApplicationServiceProvider from ServiceProviderCache

@AndriySvyryd AndriySvyryd added this to the 6.0.x milestone Jan 14, 2022
@AndriySvyryd AndriySvyryd requested a review from a team January 14, 2022 17:26
@ajcvickers
Copy link
Member

@AndriySvyryd Couldn't the IMemoryCache also cause the same issue?

@roji
Copy link
Member

roji commented Jan 18, 2022

Is there a danger of the application service provider being collected too early under memory pressure, though it may still be needed? (I don't know this area too well)

Given that DbContextOptions is already immutable and that OptionsExtensions can be cloned, would it be simpler/safer to just put a cloned copy of DbContextOptions in the ConcurrentDictionary, where the service provider has been nulled out?

@ajcvickers
Copy link
Member

Is there a danger of the application service provider being collected too early under memory pressure, though it may still be needed? (I don't this area too well)

No, because if anything else has a reference to it, then it won't be GC'ed. But if this is the only reference, then it can be GC'ed.

Given that DbContextOptions is already immutable and that OptionsExtensions can be cloned, would it be simpler/safer to just put a cloned copy of DbContextOptions in the ConcurrentDictionary, where the service provider has been nulled out?

I think it's worth exploring this.

@AndriySvyryd
Copy link
Member Author

@AndriySvyryd Couldn't the IMemoryCache also cause the same issue?

We don't store services in IMemoryCache and since it's a singleton we don't support it being disposed.

@wtgodbe wtgodbe merged commit 1f14e85 into release/6.0 Feb 2, 2022
@wtgodbe wtgodbe deleted the Issue27169 branch February 2, 2022 17:37
@ajcvickers ajcvickers removed this from the 6.0.3 milestone Feb 3, 2022
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.

5 participants