Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Conversation

@PashaPash
Copy link

Fixed deadlock between ResourceSet iterator and and ResourceSet.GetObject.

Using both ResourceSet iterator and ResourceSet.GetObject is a common scenario in web app - resource set is used for server view rendering (through ResourceSet.GetObject) and in the time that resource set is offloaded to client side as JSON (through ResourceSet iterator). There is a high probability that app will deadlock on start in that case.

Connect Issue: #580259 - closed as non-reproducable. I have no access to the source code in that connect issue, but deadlock graph seems to be exactly the same as in my sample app.

Sample app to reproduce the issue: https://github.com/PashaPash/ResManDeadlock

Details from Stack Exchange thread:

The problem is that when using a ResourceSet the iterator takes out locks on the internal resource cache of the ResourceReader http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,1389 and then in the method AllocateStringNameForIndex takes out a lock on the reader itself: http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,447

lock (_reader._resCache) {
     key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // locks the reader

Getting an object takes out the same locks int the opposite order:

http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,300
and http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,335

lock(Reader) {
    ....
    lock(_resCache) {
       _resCache[key] = resLocation;
    }
}

@PashaPash
Copy link
Author

I updated the commit message to match contribution guidelines

@AlexGhiondea
Copy link

Thanks for the contribution. At first glance the change look ok.

However, since this code is shared with Desktop we need to run this through additional validation to make sure we don't break anything.

Once we are sure we are not breaking anything we are going to merge it in.

@ramarag can you take a look at this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the indentation here. I am almost done running the tests. will merge when I get the updated PR
Also please do squash your commits to a single one

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ramarag, sorry for broken indentation, just tried to keep number of lines changed at minimum.

@ramarag ramarag assigned ramarag and unassigned gkhanna79 Feb 6, 2015
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
@PashaPash PashaPash force-pushed the resourceset_deadlock branch from 59393c0 to eedb57d Compare February 6, 2015 21:27
@PashaPash
Copy link
Author

I added an indentation and rebased commit to master. Please review.

@ramarag
Copy link
Member

ramarag commented Feb 7, 2015

LGTM... @jkotas can you take a look too.

@jkotas
Copy link
Member

jkotas commented Feb 7, 2015

LGTM

jkotas added a commit that referenced this pull request Feb 7, 2015
Fixed deadlock in System.Resources.ResourceSet
@jkotas jkotas merged commit 9df15b9 into dotnet:master Feb 7, 2015
@jkotas
Copy link
Member

jkotas commented Feb 7, 2015

Thank you for getting this fixed!

@PashaPash PashaPash deleted the resourceset_deadlock branch February 7, 2015 11:27
@ramarag ramarag removed their assignment Apr 27, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants