[runtime] Fix appdomain loading event ordering.
authorRodrigo Kumpera <kumpera@gmail.com>
Wed, 28 Jan 2015 21:34:19 +0000 (16:34 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 28 Jan 2015 23:25:41 +0000 (18:25 -0500)
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/domain-internals.h

index c1c316b170ea613b8e2081f9e05553d7650102bd..76e40409896c9a084361d39f4001a6879aabb1d8 100644 (file)
@@ -230,6 +230,8 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb,
        mono_install_assembly_refonly_preload_hook (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (FALSE));
        mono_install_assembly_refonly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE));
+       mono_install_assembly_postload_search_hook ((void*)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
+       mono_install_assembly_postload_refonly_search_hook ((void*)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
        mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
 
index 1cf5c9317b869a4b0ab7d26c974b4f5f4e250367..b3855758589bcf84b4ce19b0cfed5dc93cac6492 100644 (file)
@@ -1238,12 +1238,32 @@ mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly
 {
        AssemblySearchHook *hook;
 
-       if (postload)
-               mono_domain_assembly_postload_search(aname, requesting, refonly);
-
        for (hook = assembly_search_hook; hook; hook = hook->next) {
                if ((hook->refonly == refonly) && (hook->postload == postload)) {
-                       MonoAssembly *ass = hook->func (aname, hook->user_data);
+                       MonoAssembly *ass;
+                       /**
+                         * A little explanation is in order here.
+                         *
+                         * The default postload search hook needs to know the requesting assembly to report it to managed code.
+                         * The embedding API exposes a search hook that doesn't take such argument.
+                         *
+                         * The original fix would call the default search hook before all the registered ones and pass
+                         * the requesting assembly to it. It works but broke a very suddle embedding API aspect that some users
+                         * rely on. Which is the ordering between user hooks and the default runtime hook.
+                         *
+                         * Registering the hook after mono_jit_init would let your hook run before the default one and
+                         * when using it to handle non standard app layouts this could save your app from a massive amount
+                         * of syscalls that the default hook does when probing all sorts of places. Slow targets with horrible IO
+                         * are all using this trick and if we broke this assumption they would be very disapointed at us.
+                         *
+                         * So what's the fix? We register the default hook using regular means and special case it when iterating
+                         * over the registered hooks. This preserves ordering and enables managed resolve hooks to get the requesting
+                         * assembly.
+                         */
+                       if (hook->func == (void*)mono_domain_assembly_postload_search)
+                               ass = mono_domain_assembly_postload_search (aname, requesting, refonly);
+                       else
+                               ass = hook->func (aname, hook->user_data);
                        if (ass)
                                return ass;
                }
index 8f494f7957e2ffb9e4960c8615dc9327f813cabe..ca3d6cdba3d51c35e564713404e953bf2cd65f9c 100644 (file)
@@ -664,7 +664,7 @@ MonoReflectionAssembly *
 mono_try_assembly_resolve (MonoDomain *domain, MonoString *fname, MonoAssembly *requesting, gboolean refonly) MONO_INTERNAL;
 
 MonoAssembly *
-mono_domain_assembly_postload_search (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly);
+mono_domain_assembly_postload_search (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly) MONO_INTERNAL;
 
 MonoAssembly* mono_assembly_load_full_nosearch (MonoAssemblyName *aname, 
                                                const char       *basedir,