-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Bugfix/30024 problem with concurrency type descriptor getconverter #85156
Bugfix/30024 problem with concurrency type descriptor getconverter #85156
Conversation
Tagging subscribers to this area: @dotnet/area-system-componentmodel Issue DetailsThis PR fix #30024 .
|
f3e9d88
to
4693f40
Compare
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Outdated
Show resolved
Hide resolved
...libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj
Outdated
Show resolved
Hide resolved
0f46857
to
e9e137e
Compare
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.ComponentModel.TypeConverter/tests/TypeDescriptionProviderTests.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At quick glance, this doesn't look like a valid change.
The NodeFor method calls CheckDefaultProvider which takes the lock on s_internalSyncObject, and AddProvider calls NodeFor while holding a lock on s_providerTable. That means while holding s_providerTable the implementation can then take a lock on s_internalSyncObject. This change, though, is extending the lock in CheckDefaultProvider such that while holding the lock on s_internalSyncObject, it calls AddProvider, which will try to take a lock on s_providerTable. That means two threads could now deadlock: one holds the lock on s_providerTable and tries to acquire the lock on s_internalSyncObject, and the other holds the lock on s_internalSyncObject and tries to acquire the lock on s_providerTable.
e9e137e
to
92254ef
Compare
@stephentoub , thanks for your comment and attention. I had fixed this problem by ReaderWriterLockSlim and made amend of my commits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latest rebase\changes look like they address the feedback from @stephentoub.
I've not re-reviewed to determine whether there might still be the potential for deadlocks. Also, what's the perf impact? It's now taking a reader lock on a path that wasn't previously locked. |
@stephentoub , could you provide some info about steps for perfomance measurement for TypeDescriptor inside current repository? I usually prefer to use BenchmarkDotNet inside console application, but I don't know how to apply this way for profiling code inside .NET Runtime. |
We do have official benchmarks, but even those call public APIs. Would using variants of your tests with BenchmarkDotNet measure the extra read lock? If the test is very fast, you may want an inner loop within the benchmark method. |
I had create special branch bugfix/30024-problem-with-concurrency-typeDescriptor-getconverter(NEW), where I trying to add required tests. After that, I had build Runtime by
And I can't figure out how to fix this problem. May be somebody could explain me steps for running BenchmarkDotNet inside current repository, as I asked earlier. |
If I run already existed perfomance tests from dotnet/performance by command, then I receive next result:
that is, performance of TypeDescriptor.GetConverter has degraded by about 20% |
That seems reasonable to me. |
@stephentoub , also lets look to one more branch of my repository: 30024-problem-with-concurrency-typeDescriptor-getconverter(NEW). It contains one more little optimization which provide next result:
As you can see, perfomance degradation has decreased to 10% after commit 92a2d245958ce41e05398580c0ea45419e05effe. May be it's ok? What do you think? |
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Outdated
Show resolved
Hide resolved
92254ef
to
1f20655
Compare
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Show resolved
Hide resolved
src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs
Show resolved
Hide resolved
@stephentoub - PTAL again thanks |
Closing this PR for v8 due to risk + schedule; ideally should be done early in the 9.0 branch. There is risk in this PR and we need more time to verify this than what we have left in v8 -- RC1 is almost done. @Maximys thanks for this PR. cc @JeremyKuhne - thoughts on fixing this? This issue also occurs in .NET Framework to my knowledge. |
This PR fix #30024 .
Problem was linked with race condition inside private method System.ComponentModel.TypeDescriptor.CheckDefaultProvider(Type).
I think, it'll better to change base type of WeakHashtable from Hashtable to ConcurrentDictionary<TKey,TValue> and use method GetOrAdd(TKey, Func<TKey,TValue>), but this changes can be very dangerous and I'm afraid to do them.