Skip to content

Commit 3d89cb5

Browse files
committed
Fix InitializeConstructors race condition
1 parent b138092 commit 3d89cb5

1 file changed

Lines changed: 15 additions & 6 deletions

File tree

src/SIL.LCModel/Infrastructure/Impl/CmObjectSurrogate.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace SIL.LCModel.Infrastructure.Impl
3333
internal sealed class CmObjectSurrogate : ICmObjectSurrogate //, IEquatable<CmObjectSurrogate>
3434
{
3535
private static Dictionary<string, ConstructorInfo> s_classToConstructorInfo;
36+
private static readonly object s_constructorLock = new object();
3637
/// <summary>
3738
/// It's common that hundreds of thousands of surrogates only use a few hundred class names. This is a local interning
3839
/// of those names.
@@ -227,14 +228,22 @@ internal static void InitializeConstructors(List<Type> cmObjectTypes)
227228
{
228229
if (s_classToConstructorInfo != null) return;
229230

230-
s_classToConstructorInfo = new Dictionary<string, ConstructorInfo>();
231-
// Get default constructor.
232-
// Only do this once, since they are stored in a static data member.
233-
foreach (var lcmType in cmObjectTypes)
231+
lock (s_constructorLock)
234232
{
235-
if (lcmType.IsAbstract) continue;
233+
if (s_classToConstructorInfo != null) return;
236234

237-
s_classToConstructorInfo.Add(lcmType.Name, lcmType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
235+
var dict = new Dictionary<string, ConstructorInfo>();
236+
// Get default constructor.
237+
// Only do this once, since they are stored in a static data member.
238+
foreach (var lcmType in cmObjectTypes)
239+
{
240+
if (lcmType.IsAbstract) continue;
241+
242+
dict.Add(lcmType.Name, lcmType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
243+
}
244+
245+
// Assign only after fully populated so the outer null check never sees a partial dictionary
246+
s_classToConstructorInfo = dict;
238247
}
239248
}
240249

0 commit comments

Comments
 (0)