Reputation: 5688
I'm facing a troubling situation.
I've got a dictionary which holds a null key entry...
This happens from time to time in my iis application, which then freezes when a lookup is performed on this dictionary (100% cpu, infinite loop):
Sources of FindEntry method (both uncompiled or reference sources) are pretty clear:
1) Having a null key in a dictionary is NOT possible
2) The infinite loop is pretty obvious given my dictionary private field:
Any idea on happens to me ?
ps: I do not have any funny thing installed like ryujit or custom .net build. Just a regular iisexpress running under .Net 4.5
edit
As requested (i should have precised): I'm not doing anything funny with this dictionary either. Only one usage:
if (!readers.TryGetValue(type, out ret))
readers[type] = ret = GetReaderOfTMethod.MakeGenericMethod(type).Invoke(this,null);
Upvotes: 1
Views: 1200
Reputation: 113242
If this dictionary isn't restricted to a single thread (created within a method and used there, but stored statically) then I'd expect this to happen.
Dictionary
is written, like any other code, with assumptions about what can have previously happened to it. These assumptions don't consider simultaneous calls so e.g. it's assumed that if the dictionary is being resized, that the resize won't happen again until that resize is finished, that only one attempt will be made to set a given value at a time, and so on.
Don't guard against this, and two calls can put the dictionary into a state that its coders didn't consider and then things that don't make sense can happen, like having a null key even though null keys aren't allowed.
If such simultaneous use isn't going to be common (and it would seem it won't), then guard every access with a lock:
lock(lockObj)
if (!readers.TryGetValue(type, out ret))
readers[type] = ret = GetReaderOfTMethod.MakeGenericMethod(type).Invoke(this,null);
Where lockObj
is an object at the same scope as readers
which is used to lock all access to it. (Likely readers
would work well as the lock object itself here, but when that is and isn't a good idea is another topic in itself).
If there are any other uses of reader
they should also be locked using the same lock object.
If such simultaneous use is going be common then a concurrent dictionary that is designed to tolerate such uses would be better (ConcurrentDictionary
in the framework, or my ThreadsafeDictionary
will both work). These tend to be less efficient generally, but more efficient above a certain level of concurrent uses.
Upvotes: 3