-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
System.Resources.ResourceManager is not thread safe when ignore case is enabled #74052
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/area-system-resources Issue DetailsDescriptionI'm using ResrouceManager to access the resources file in satellite assemblies, and the function is working fine as expected, however I cannot get expected value if I turn on the ignore case for the Resrouce Manager. Reproduction Steps
Following is the validation code to verify the value
Expected behaviorThe expected value should be the lower case of the key. Actual behaviorBelow is the output, you can see the the value for E is not e, it's ☺, and some tasks have exception to get value. E -> ☺ Regression?No response Known WorkaroundsThe workaround is to add lock for the GetString method to prevent concurrent access. Configuration
Other informationThe GetObject method in RuntimeResourceSet has two lock, and I believe we should use one lock for all cases because the second lock cannot lock it when multiple threads call this method.
|
That seems like a bug as GetString should be thread safe. |
@danmoseley looks you are correct. Some fields in the |
The locking in this and its related classes needs some auditing, and it would probably be helpful to add some |
Doesn't seem regression, adding to future milestone for now, @danmoseley @tarekgh feel free to prioritize as needed |
should we mark help wanted? |
I'd be interested in working on this. |
It's yours @madelson |
Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix dotnet#74052 Fix dotnet#74868
* Fix thread-safety issues with enumerating ResourceManager. Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868 * Remove trailing whitespace * Address feedback from #75054 * Add comment in response to #75054 (comment) * Implement feedback from #75054
Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868
Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868
Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868
…er. (#81283) * Fix thread-safety issues with enumerating ResourceManager. Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868 * Remove trailing whitespace * Address feedback from #75054 * Add comment in response to #75054 (comment) * Implement feedback from #75054 * Increase timeout for TestResourceManagerIsSafeForConcurrentAccessAndEnumeration (#80330) This raises the timeout to 30s, the same as what we have for the equivalent ResourceManager test (https://github.com/dotnet/runtime/blob/15fcb990fe17348ab6ddde0939200b900169920b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs#L255). fix #80277 --------- Co-authored-by: Michael Adelson <[email protected]> Co-authored-by: madelson <[email protected]> Co-authored-by: Buyaa Namnan <[email protected]>
…er. (#81281) * Fix thread-safety issues with enumerating ResourceManager. Concurrently enumerating a ResourceManager while also calling GetString() and similar methods was prone to both transient errors and deadlock. The transient errors were caused by RuntimeResourceSet calling internal methods on ResourceReader that did not properly lock. Now, all exposed methods on the Reader are thread-safe. The deadlock was called by inconsistent lock ordering between ResourceReader.ResourceEnumerator and RuntimeResourceSet which both lock on the RuntimeResourceSet's cache and on the ResourceReader itself. Now, the enumerator does not need to take both locks at the same time. Fix #74052 Fix #74868 * Remove trailing whitespace * Address feedback from #75054 * Add comment in response to #75054 (comment) * Implement feedback from #75054 * Increase timeout for TestResourceManagerIsSafeForConcurrentAccessAndEnumeration (#80330) This raises the timeout to 30s, the same as what we have for the equivalent ResourceManager test (https://github.com/dotnet/runtime/blob/15fcb990fe17348ab6ddde0939200b900169920b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs#L255). fix #80277 --------- Co-authored-by: Michael Adelson <[email protected]> Co-authored-by: madelson <[email protected]> Co-authored-by: Carlos Sanchez <[email protected]> Co-authored-by: Buyaa Namnan <[email protected]>
Description
I'm using ResrouceManager to access the resources file in satellite assemblies, and the function is working fine as expected, however I cannot get expected value if I turn on the ignore case for the Resrouce Manager.
Reproduction Steps
Following is the validation code to verify the value
Expected behavior
The expected value should be the lower case of the key.
Actual behavior
Below is the output, you can see the the value for E is not e, it's ☺, and some tasks have exception to get value.
E -> ☺
System.FormatException: Corrupt .resources file. Invalid offset '23593217' into data section.
at System.Resources.ResourceReader.AllocateStringForNameIndex(Int32 index, Int32& dataOffset)
at System.Resources.ResourceReader.ResourceEnumerator.get_Key()
at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase, Boolean isString)
at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
at System.Resources.ResourceManager.GetString(String name)
at MyApp.Program.TestResource(ResourceManager manager, String key, Flags flags)
Regression?
No response
Known Workarounds
The workaround is to add lock for the GetString method to prevent concurrent access.
Configuration
.Net 6
Windows 11, [Version 10.0.22000.856]
x64
I don't think so.
N/A
Other information
The GetObject method in RuntimeResourceSet has two lock, and I believe we should use one lock for all cases because the second lock cannot lock it when multiple threads call this method.
The text was updated successfully, but these errors were encountered: