Skip to content

Commit bbb9bdd

Browse files
author
Mohamed Koubaa
committed
PR review feedback
1 parent 1761cb0 commit bbb9bdd

File tree

1 file changed

+41
-20
lines changed

1 file changed

+41
-20
lines changed

netfx_loader/DomainData.cs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,26 @@ namespace ClrLoader
1010
public static class DomainSetup
1111
{
1212
public delegate int EntryPoint(IntPtr buffer, int size);
13+
1314
public static void StoreFunctorFromDomainData()
1415
{
1516
var domain = AppDomain.CurrentDomain;
1617
var assemblyPath = (string)domain.GetData("_assemblyPath");
1718
var typeName = (string)domain.GetData("_typeName");
1819
var function = (string)domain.GetData("_function");
19-
var functor = GetFunctor(domain, assemblyPath, typeName, function);
20+
var deleg = GetDelegate(domain, assemblyPath, typeName, function);
21+
var functor = Marshal.GetFunctionPointerForDelegate(deleg);
22+
domain.SetData("_thisDelegate", deleg);
2023
domain.SetData("_thisFunctor", functor);
2124
}
2225

23-
private static IntPtr GetFunctor(AppDomain domain, string assemblyPath, string typeName, string function)
26+
private static Delegate GetDelegate(AppDomain domain, string assemblyPath, string typeName, string function)
2427
{
25-
var assemblyName = AssemblyName.GetAssemblyName(assemblyPath).Name;
26-
var assembly = domain.Load(AssemblyName.GetAssemblyName(assemblyPath));
28+
var assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
29+
var assembly = domain.Load(assemblyName);
2730
var type = assembly.GetType(typeName, throwOnError: true);
2831
var deleg = Delegate.CreateDelegate(typeof(EntryPoint), type, function);
29-
IntPtr result = Marshal.GetFunctionPointerForDelegate(deleg);
30-
return result;
32+
return deleg;
3133
}
3234
}
3335

@@ -61,27 +63,46 @@ private void installResolver(string assemblyPath)
6163
};
6264
}
6365

66+
private static readonly object _lockObj = new object();
67+
6468
public IntPtr GetFunctor(string assemblyPath, string typeName, string function)
6569
{
6670
if (_disposed)
6771
throw new InvalidOperationException("Domain is already disposed");
6872

69-
installResolver(assemblyPath);
70-
71-
var key = (assemblyPath, typeName, function);
72-
73-
IntPtr result;
74-
if (!_functors.TryGetValue(key, out result))
73+
// neither the domain data nor the _functors dictionary is threadsafe
74+
lock (_lockObj)
7575
{
76-
Domain.SetData("_assemblyPath", assemblyPath);
77-
Domain.SetData("_typeName", typeName);
78-
Domain.SetData("_function", function);
79-
80-
Domain.DoCallBack(new CrossAppDomainDelegate(DomainSetup.StoreFunctorFromDomainData));
81-
result = (IntPtr)Domain.GetData("_thisFunctor");
82-
_functors[key] = result;
76+
installResolver(assemblyPath);
77+
var assemblyName = AssemblyName.GetAssemblyName(assemblyPath).Name;
78+
79+
var key = (assemblyName, typeName, function);
80+
81+
IntPtr result;
82+
if (!_functors.TryGetValue(key, out result))
83+
{
84+
Domain.SetData("_assemblyPath", assemblyPath);
85+
Domain.SetData("_typeName", typeName);
86+
Domain.SetData("_function", function);
87+
88+
Domain.DoCallBack(new CrossAppDomainDelegate(DomainSetup.StoreFunctorFromDomainData));
89+
result = (IntPtr)Domain.GetData("_thisFunctor");
90+
if (result == IntPtr.Zero)
91+
throw new Exception($"Unable to get functor for {assemblyName}, {typeName}, {function}");
92+
93+
// set inputs to StoreFunctorFromDomainData to null.
94+
// (There's no method to explicitly clear domain data)
95+
Domain.SetData("_assemblyPath", null);
96+
Domain.SetData("_typeName", null);
97+
Domain.SetData("_function", null);
98+
99+
// the result has to remain in the domain data because we don't know when the
100+
// client of pyclr_get_function will actually invoke the functor, and if we
101+
// remove it from the domain data after returning it may get collected too early.
102+
_functors[key] = result;
103+
}
104+
return result;
83105
}
84-
return result;
85106
}
86107

87108
public void Dispose()

0 commit comments

Comments
 (0)