summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPavel Pochobut <pavel.pochobut@gmail.com>2015-02-04 21:49:32 +0300
committerPavel Pochobut <pavel.pochobut@gmail.com>2015-02-07 00:26:51 +0300
commiteedb57dff27884ee4d3539ce3eda283408aea3ae (patch)
tree270006668c5216fc556097221a07414e169bc130 /src
parentc4eb03708c4c09b47fcdf6a77e6a9abe8952ce9f (diff)
downloadcoreclr-eedb57dff27884ee4d3539ce3eda283408aea3ae.tar.gz
coreclr-eedb57dff27884ee4d3539ce3eda283408aea3ae.tar.bz2
coreclr-eedb57dff27884ee4d3539ce3eda283408aea3ae.zip
Fixed deadlock in System.Resources.ResourceSet
ResourceSet internal enumerator uses the following lock order: 1. lock _resCache (as _reader._resCache) in System.Resources.ResourceSet+ResourceEnumerator.Entry 2. lock reader (this) in the body on of _reader.AllocateStringForNameIndex RuntimeResourceSet.GetObject uses the following lock order: 1. Lock on reader 2. Lock on _resCache (on the same instance as passed to the reader ctor) That causes deadlock when one thread tries to enumerate the ResourceSet while another thread reads a specific object from the same set. Added lock in System.Resources.ResourceSet+ResourceEnumerator.Entry, so both code paths locks on reader first. Fix Connect Issue ID #580259
Diffstat (limited to 'src')
-rw-r--r--src/mscorlib/src/System/Resources/ResourceReader.cs34
1 files changed, 18 insertions, 16 deletions
diff --git a/src/mscorlib/src/System/Resources/ResourceReader.cs b/src/mscorlib/src/System/Resources/ResourceReader.cs
index 4430ca6328..a811fae194 100644
--- a/src/mscorlib/src/System/Resources/ResourceReader.cs
+++ b/src/mscorlib/src/System/Resources/ResourceReader.cs
@@ -1373,22 +1373,24 @@ namespace System.Resources {
String key;
Object value = null;
- lock (_reader._resCache) {
- key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition);
- ResourceLocator locator;
- if (_reader._resCache.TryGetValue(key, out locator)) {
- value = locator.Value;
- }
- if (value == null) {
- if (_dataPosition == -1)
- value = _reader.GetValueForNameIndex(_currentName);
- else
- value = _reader.LoadObject(_dataPosition);
- // If enumeration and subsequent lookups happen very
- // frequently in the same process, add a ResourceLocator
- // to _resCache here. But WinForms enumerates and
- // just about everyone else does lookups. So caching
- // here may bloat working set.
+ lock (_reader) { // locks should be taken in the same order as in RuntimeResourceSet.GetObject to avoid deadlock
+ lock (_reader._resCache) {
+ key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // AllocateStringForNameIndex could lock on _reader
+ ResourceLocator locator;
+ if (_reader._resCache.TryGetValue(key, out locator)) {
+ value = locator.Value;
+ }
+ if (value == null) {
+ if (_dataPosition == -1)
+ value = _reader.GetValueForNameIndex(_currentName);
+ else
+ value = _reader.LoadObject(_dataPosition);
+ // If enumeration and subsequent lookups happen very
+ // frequently in the same process, add a ResourceLocator
+ // to _resCache here. But WinForms enumerates and
+ // just about everyone else does lookups. So caching
+ // here may bloat working set.
+ }
}
}
return new DictionaryEntry(key, value);