You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Deadlock when enumerating resources with ResourceManager #74868
Enumerating resources with ResourceManager.GetResourceSet while concurrently calling ResourceManager.GetString can result in a hang which appears to be due to deadlock.
Reproduction Steps
The following code snippet hangs with high probability on .NET 6. Most commonly, this happens after printing the first entry on each thread.
voidMain(){varresourceType=typeof(MyResource);// standard resx with 15 entriesvarresourceManager=newResourceManager(resourceType.FullName,resourceType.Assembly);varthreads=10;usingvarbarrier=newBarrier(threads);Task.WaitAll(Enumerable.Range(0,threads).Select(_ =>Task.Run(()=>{barrier.SignalAndWait();EnumerateResources();})).ToArray());// never returnsvoidEnumerateResources(){varset=resourceManager.GetResourceSet(CultureInfo.InvariantCulture,createIfNotExists:true,tryParents:true);foreach(varentryinset.Cast<DictionaryEntry>()){Console.WriteLine(resourceManager.GetString((string)entry.Key));Thread.Sleep(1);}}}
Expected behavior
ResourceManager is supposed to be thread safe, so this code should work.
Actual behavior
Frequent hangs.
Regression?
I know that this used to be broken in some early versions of .NET Framework as well and was fixed at some point (perhaps in one of the 4.6 releases?). Testing the same snippet on .NET Framework latest does not hang, so I believe this is a regression.
EDIT: based on further testing this appears to be a regression vs. .NET Core 3.1 as well.
Known Workarounds
Allocate a new ResourceManager instance when planning to call GetResourceSet rather than re-using a shared instance.
Another sort-of workaround is to use the Key property on the enumerator instead of the Current property. This avoids the deadlock and makes more progress, but we instead run into #74052 .
Thanks for the report @madelson, and also for checking when did this regressed. From your original post though, I see that this issue was present in .NET 6 (meaning it wasn't a regression from .NET 6 to .NET 7), so I'm going to move this issue out of .NET 7 by setting the milestone to .NET 8 for now. Thanks again for working on this!
@joperezr it isn't a regression from 6->7, but it is a regression from the previous LTS release (3.1) to the current LTS release (6). I imagine that the bar is too high to consider backporting this to 6 but given the severity of the issue if you encounter it (deadlocking the app) and the fact that apps may be unprepared for this given its previous fix, it would be nice to at least consider that.
That's right, I didn't mean that this shouldn't get fixed in servicing, sorry for not making that clear. What I meant was that the fix is likely not going to hit .NET 7 before we ship, so I just adjusted the milestone to vNext for now. The process to get this regression fixed in servicing would be to:
Fix the issue in main branch (which today means 8.0 and the reason why I picked that milestone)
Once the fix is ready and we have validated that the fix works as expected, we can then make a case for us to service this in all impacted releases (which would be 6.0, and 7.0). If approved, then we can cherry-pick the change from main into those servicing branches and create PRs for them in order to get the fix serviced.
Activity
madelson commentedon Aug 31, 2022
I'd be happy to work on this as part of working on #74052
Fix thread-safety issues with enumerating ResourceManager.
joperezr commentedon Sep 6, 2022
Thanks for the report @madelson, and also for checking when did this regressed. From your original post though, I see that this issue was present in .NET 6 (meaning it wasn't a regression from .NET 6 to .NET 7), so I'm going to move this issue out of .NET 7 by setting the milestone to .NET 8 for now. Thanks again for working on this!
madelson commentedon Sep 6, 2022
@joperezr it isn't a regression from 6->7, but it is a regression from the previous LTS release (3.1) to the current LTS release (6). I imagine that the bar is too high to consider backporting this to 6 but given the severity of the issue if you encounter it (deadlocking the app) and the fact that apps may be unprepared for this given its previous fix, it would be nice to at least consider that.
joperezr commentedon Sep 6, 2022
That's right, I didn't mean that this shouldn't get fixed in servicing, sorry for not making that clear. What I meant was that the fix is likely not going to hit .NET 7 before we ship, so I just adjusted the milestone to vNext for now. The process to get this regression fixed in servicing would be to:
Fix thread-safety issues with enumerating ResourceManager. (#75054)
Fix thread-safety issues with enumerating ResourceManager.
Fix thread-safety issues with enumerating ResourceManager.
Fix thread-safety issues with enumerating ResourceManager.
[release/7.0] Fix thread-safety issues with enumerating ResourceManag…
[release/6.0] Fix thread-safety issues with enumerating ResourceManag…