1. Aristarkh Zagorodnikov
  2. ResManRC


This code demonstrates a race condition that exists somewhere in System.Resources.ResourceManager of .NET 4.5 (it's probably present there from 4.0). Running is simple: choose shared or private mode (see below) and type "ResManRC shared" or "ResManRC private".
The race condition leads to internal cache corruption that prevents proper resource fallback. The easiest way to get this condition is to try to get a resource that does not exist in one of the localized versions, using specific culture ("language-COUNTRY"), so the fallback mechanism is triggered.
This project contains a resource file (Resources.resx) that contains a single string with key "Name", along with a "localized" Russian version of it (Resources.ru.resx) that is empty.
The expected behavior is that getting the "Name"-keyed string would work no matter what culture is used in the request.
With single-threaded versions of the code, it works both for private or shared resource managers. Unfortunately, multithreaded versions lead to missing string value, permanently "damaging" the resource manager in shared case and affecting only one copy of the manager in the private case.
Since even the private case is affected (in private mode, ResourceManager instances are not shared between threads), it appears that the race condition does not lie within ResourceManager itself, rather it is located somewhere deeper in the framework code.
Please take note, that since this is a repro for a race condition, it might not work out of the box, using a machine with at least 4 physical cores is recommended for reliable (>85%) repro success.
While it is unlikely to be triggered in GUI applications, we observed this bug manifesting itself on ASP.NET web servers leading to incorrect resources being used by the website, until the application domain is recycled. We are not the only ones with the same problem, for example check http://stackoverflow.com/questions/17652351/.