[loader] Init MonoClass:sizes.element_size lazily (Fixes #43563) (#5559)
[mono.git] / mono / metadata / loader.c
index 85b5639384b1e70c1ac590fc5dd5d3108ea336d0..5281a5d39b882e00e1a16c5dc39c23ce1aa22bf8 100644 (file)
@@ -74,6 +74,7 @@ static gint32 signatures_size;
 MonoNativeTlsKey loader_lock_nest_id;
 
 static void dllmap_cleanup (void);
+static void cached_module_cleanup(void);
 
 static void
 global_loader_data_lock (void)
@@ -117,6 +118,7 @@ void
 mono_loader_cleanup (void)
 {
        dllmap_cleanup ();
+       cached_module_cleanup ();
 
        mono_native_tls_free (loader_lock_nest_id);
 
@@ -312,9 +314,17 @@ mono_field_from_token_checked (MonoImage *image, guint32 token, MonoClass **retk
                mono_class_init (k);
                if (retklass)
                        *retklass = k;
-               field = mono_class_get_field (k, token);
-               if (!field) {
-                       mono_error_set_bad_image (error, image, "Could not resolve field token 0x%08x", token);
+               if (mono_class_has_failure (k)) {
+                       MonoError causedby_error;
+                       error_init (&causedby_error);
+                       mono_error_set_for_class_failure (&causedby_error, k);
+                       mono_error_set_bad_image (error, image, "Could not resolve field token 0x%08x, due to: %s", token, mono_error_get_message (&causedby_error));
+                       mono_error_cleanup (&causedby_error);
+               } else {
+                       field = mono_class_get_field (k, token);
+                       if (!field) {
+                               mono_error_set_bad_image (error, image, "Could not resolve field token 0x%08x", token);
+                       }
                }
        }
 
@@ -1137,6 +1147,23 @@ mono_loader_register_module (const char *name, MonoDl *module)
        g_hash_table_insert (global_module_map, g_strdup (name), module);
 }
 
+static void
+remove_cached_module(gpointer key, gpointer value, gpointer user_data)
+{
+       mono_dl_close((MonoDl*)value);
+}
+
+static void
+cached_module_cleanup(void)
+{
+       if (global_module_map != NULL) {
+               g_hash_table_foreach(global_module_map, remove_cached_module, NULL);
+
+               g_hash_table_destroy(global_module_map);
+               global_module_map = NULL;
+       }
+}
+
 static MonoDl *internal_module;
 
 static gboolean