-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: 2.25.0
-
Component/s: Serialization
-
None
-
Fully Compatible
-
Dotnet Drivers
-
Not Needed
-
Hi,
During using the MongoDrive, I encounter a deadlock issue which cause the whole application loading data blocked. After doing few research, I figured out the issue was caused by two collections had the same generic parameters, but different dictionary representaion properties.
Two threads' call stack as follows:
A Thread:
-> DictionarySerializerBase<TDictionary, TKey, TValue>.DeserializeValue
-> Lazy<T>.CreateValue
-> Lazy<T>.ExecutionAndPublication
-> Lazy<T>.ViaFactory
-> BsonSerializerRegistry.GetSerializer
-> BsonClassMapSerializationProvider.GetSerializer
-> BsonClassMap.LookupClassMap
-> BsonSerializer.ConfigLock.EnterReadLock (deadlock)
B Thread:
-> BsonSerializerRegistry.CreateSerializer
-> BsonClassMap.LookupClassMap
-> BsonSerializer.ConfigLock.EnterWriteLock
-> BsonClassMap.AutoMap
-> AttributeConventionPack+AttributeConvention.Apply
-> DictionaryInterfaceImplementerSerializer<TDictionary, TKey, TValue>.WithDictionaryRepresentation
-> DictionarySerializerBase.get_ValueSerializer
-> Lazy<T>.CreateValue
-> Lazy<T>.ExecutionAndPublication (deadlock)
1. Thread A first used the default seirializer and registered the DictionaryInterfaceImplementerSerializer
to the
** BsonSerializerRegistry.
Visited the
**
ValueSerializer and casued a lazy object to be created. Finally the thread started to wait for the read lock.
2. Tread B then used the non-default seirializer. The thread got the readlock and need to get a instance from the DictionaryInterfaceImplementerSerializer which need to visit ** its *
ValueSerializer.
*
Which caused a lazy object creation and lock.
This bug can reproduced by the code below
var testData = new TestData { Items = new Dictionary<string, Item>() { { "1", new Item() } } }; var testData2 = new TestData2 { Items = new Dictionary<string, Item>() { { "2", new Item() } } }; BsonSerializer.SerializerRegistry.GetSerializer<Dictionary<int, Item>>(); _ = Task.Run(() => { var stream = new MemoryStream(); using var bsonWriter = new BsonBinaryWriter(stream); BsonSerializer.Serialize(bsonWriter, testData); }); await Task.Delay(TimeSpan.FromMilliseconds(100)); { var stream = new MemoryStream(); using var bsonWriter = new BsonBinaryWriter(stream); BsonSerializer.Serialize(bsonWriter, testData2); } Console.WriteLine("Hello, World!"); public class Item; public class TestData { public Dictionary<string, Item> Items { get; set; } = new(); } public class TestData2 { [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)] public Dictionary<string, Item> Items { get; set; } = new(); }
The modification in the driver as the attachment shows can also increase the probibility to reproduce this issue.
Best Regards.
Renqiu