I'm working on a huge system based on Asp.net MVC 3.0 and working on Mono-2.10.8 (Windows 7).
Everything was fine until a moment couple of days ago.
Inside my API I have several utility classes using dictionaries. For example, like this one:
public static class KeyUtility
{
static KeyUtility() {
Alphabet = new[] {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S',
'T', 'U', 'V', 'X', 'Y', 'Z', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9'
};
ReverseAlphabet = Alphabet
.Select((c, i) => new { Char = c, Value = i })
.ToDictionary(k => k.Char, v => (byte) v.Value);
}
internal static char[] Alphabet;
private static IDictionary<char, byte> ReverseAlphabet;
public static string ToKey(byte[] key, int groupSize)
{
//Accessing Alphabet to generate string key from bytes
}
public static byte[] FromKey(string key)
{
//Accessing ReverseAlphabet to get bytes from string key
}
}
And randomly I get exceptions like this:
System.IndexOutOfRangeException: Array index is out of range.
at System.Collections.Generic.Dictionary`2<char, byte>.TryGetValue (char,byte&) <0x000a1>
at MyAPI.KeyUtility.FromKey (string) <0x0009a>
at MyApp.Controllers.AboutController.Index () <0x002df>
at (wrapper dynamic-method) object.lambda_method (System.Runtime.CompilerServices.Closure,System.Web.Mvc.ControllerBase,object[]) <0x0002f>
at System.Web.Mvc.ActionMethodDispatcher.Execute (System.Web.Mvc.ControllerBase,object[]) <0x0001b>
at System.Web.Mvc.ReflectedActionDescriptor.Execute (System.Web.Mvc.ControllerContext,System.Collections.Generic.IDictionary`2<string, object>) <0x000ff>
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod (System.Web.Mvc.ControllerContext,System.Web.Mvc.ActionDescriptor,System.Collections.Generic.IDictionary`2<string, object>) <0x00019>
at System.Web.Mvc.ControllerActionInvoker/<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12 () <0x00066>
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (System.Web.Mvc.IActionFilter,System.Web.Mvc.ActionExecutingContext,System.Func`1<System.Web.Mvc.ActionExecutedContext>) <0x000b8>
Most of the time everything is fine and KeyUtility
works correct, but on rare occasions I get such an exception.
Despite it looks like thread safety issue, the dictionary ReverseAlphabet
is always accessed for reading only and never for writing. Once it's created in static constructor it's only accessed with TryGetValue
. As I understand from MSDN article it should be thread safe in this case.
Moreover, I haven't seen this problem before.
What should I look at? I even can't create a reproduction as I have completely no idea what is wrong.
Mono-2.10.8 and older versions proved to be stable with dictionaries. I've been using it for a couple of years intensively and have never seen this sort of exception before.
How to fix this?
UPD:
I've remembered that near the time of the begining of troubles what i've done is statically linked mono with my executable (i'm embedding mono into my application). I simply downloaded sources of mono. Compilled it without any changes except i set up libmono's output to static library. I've also linked with libeay32 and sqlite3. All multithread (MT). Maybe this change could affect an application? Unfortunately i can't check this under standalone mono. Before this i was linking all libraries dynamically and everything was fine.
UPD2: Here is the link to the complete sources: http://pastebin.com/RU4RNCki