Skip to content

Commit b3ee0f2

Browse files
[release/9.0.1xx] [ObjCRuntime] Ensure all assemblies' module constructors have executed before failing registrar lookup. (#21891)
The managed static registrar depends on each assembly registering itself to find types from that assembly. This is done using a module constructor, but the module constructor isn't necessarily executed before the managed static registrar needs the assembly registered (in particular for app extensions, which don't have a managed entry point). That would lead to exceptions like this: *** Terminating app due to uncaught exception 'ObjCRuntime.RuntimeException', reason: 'Could not find the type 'ObjCRuntime.__Registrar__' in the assembly '...'. (ObjCRuntime.RuntimeException) at ObjCRuntime.RegistrarHelper.GetMapEntry(String assemblyName) at ObjCRuntime.RegistrarHelper.GetMapEntry(Assembly assembly) [...] Fix this by manually calling the module constructor for every loaded assembly if we can't find it in the map of registered assemblies. Backport of #21885 Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
1 parent c29b554 commit b3ee0f2

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

src/ObjCRuntime/RegistrarHelper.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,25 @@ static MapInfo GetMapEntry (string assemblyName)
102102
{
103103
if (TryGetMapEntry (assemblyName, out var rv))
104104
return rv;
105+
106+
#if TRACE
107+
Runtime.NSLog ($"RegistrarHelper.GetMapEntry ({assemblyName}) => failed to find entry, will ensure module constructors are called for all loaded assemblies.");
108+
#endif
109+
// An assembly is only registered if we've (tried to) execute code from it, which is not guaranteed to
110+
// happen before we get here (in particular for app extensions, which don't have a managed Main method).
111+
// So here we loop over all the assemblies in the current domain, make sure the module constructor
112+
// has been called for all of them, and then we try again.
113+
var assemblies = AppDomain.CurrentDomain.GetAssemblies ();
114+
foreach (var asm in assemblies)
115+
RuntimeHelpers.RunModuleConstructor (asm.ManifestModule.ModuleHandle);
116+
117+
if (TryGetMapEntry (assemblyName, out rv))
118+
return rv;
119+
120+
#if TRACE
121+
Runtime.NSLog ($"RegistrarHelper.GetMapEntry ({assemblyName}) => failed to find entry for the second time.");
122+
#endif
123+
105124
throw ErrorHelper.CreateError (8055, Errors.MX8055 /* Could not find the type 'ObjCRuntime.__Registrar__' in the assembly '{0}' */, assemblyName);
106125
}
107126

0 commit comments

Comments
 (0)