Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

LoadFromResolve event handler should return null #12329

Merged
merged 1 commit into from
Jun 17, 2017

Conversation

gkhanna79
Copy link
Member

Since LoadFromResolve event handler is wired upto AppDomain.AssemblyResolve event, it should return null when an assembly cannot be found for any reason as AssemblyResolve event expects that (See https://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve(v=vs.110).aspx).

Fixes dotnet/corefx#21095

@jkotas @tarekgh PTAL

@tarekgh
Copy link
Member

tarekgh commented Jun 16, 2017

LGTM. just wondering, there is no way to prob loading the assembly without throwing at all instead of throwing and then catching the exception?

@gkhanna79
Copy link
Member Author

It is not just about probing the presence but for any load error. Essentially, AssemblyResolve does not expect anything but valid assembly or null from its callbacks, per the documentation.

@tarekgh
Copy link
Member

tarekgh commented Jun 16, 2017

It is not just about probing the presence but for any load error. Essentially, AssemblyResolve does not expect anything but valid assembly or null from its callbacks, per the documentation.

Yes I understand this. I am asking if we have any internal API similar to Assembly.LoadFrom which doesn't throw at all. all my point is I am trying to see if there is a way to avoid throwing and then catching for the sake of the performance and also to avoid the debuggers break on such handled exceptions.

I am ok with the change, I am just asking if we have anyway to do that :-)

@gkhanna79
Copy link
Member Author

The documentation, however, is different from implementation - https://github.com/dotnet/coreclr/blob/master/src/vm/appdomain.cpp#L7090 :(

@gkhanna79
Copy link
Member Author

Callstack at which exception is thrown in LoadFromResolve event handler:

# Child-SP          RetAddr           Call Site
00 0000004c`401e8b70 00007ffa`e0c68470 KERNELBASE!RaiseException+0x68 [minkernel\kernelbase\xcpt.c @ 904] 
01 0000004c`401e8c50 00007ffa`e016aa2d coreclr!_CxxThrowException+0x130 [f:\dd\vctools\crt\vcruntime\src\eh\throw.cpp @ 136] 
02 0000004c`401e8d00 00007ffa`e0255f11 coreclr!EEFileLoadException::Throw+0x43d [e:\gh\gkhanna79\coreclr\src\vm\clrex.cpp @ 2005] 
03 0000004c`401e90d0 00007ffa`e025657a coreclr!PEImage::GetFileHandle+0x341 [e:\gh\gkhanna79\coreclr\src\vm\peimage.cpp @ 1200] 
04 0000004c`401e9230 00007ffa`e02562c9 coreclr!PEImage::GetLayoutInternal+0x27a [e:\gh\gkhanna79\coreclr\src\vm\peimage.cpp @ 933] 
05 0000004c`401e93c0 00007ffa`e0253bf4 coreclr!PEImage::GetLayout+0xd9 [e:\gh\gkhanna79\coreclr\src\vm\peimage.cpp @ 875] 
06 0000004c`401e94d0 00007ffa`e09d6786 coreclr!PEImage::CheckILFormat+0x64 [e:\gh\gkhanna79\coreclr\src\vm\peimage.cpp @ 118] 
07 0000004c`401e9610 00007ffa`de7a690a coreclr!AssemblyNative::LoadFromPath+0x276 [e:\gh\gkhanna79\coreclr\src\vm\assemblynative.cpp @ 457] 
08 0000004c`401e9900 00007ffa`de604902 System_Private_CoreLib!DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, System.String, System.String, System.Runtime.CompilerServices.ObjectHandleOnStack)+0xaa
09 0000004c`401e99c0 00007ffa`de557e15 System_Private_CoreLib!System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(System.String)+0x132 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Runtime\Loader\AssemblyLoadContext.cs @ 94] 
0a 0000004c`401e9a70 00007ffa`de557af7 System_Private_CoreLib!System.Reflection.Assembly.LoadFrom(System.String)+0x285 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Reflection\Assembly.CoreCLR.cs @ 100] 
0b 0000004c`401e9b50 00007ffa`de4730d4 System_Private_CoreLib!System.Reflection.Assembly.LoadFromResolveHandler(System.Object, System.ResolveEventArgs)+0x267 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Reflection\Assembly.CoreCLR.cs @ 59] 
0c 0000004c`401e9c70 00007ffa`e0911a43 System_Private_CoreLib!System.AppDomain.OnAssemblyResolveEvent(System.Reflection.RuntimeAssembly, System.String)+0x154 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\AppDomain.cs @ 763] 
0d 0000004c`401e9d40 00007ffa`e055761e coreclr!CallDescrWorkerInternal+0x83 [E:\GH\gkhanna79\coreclr\src\vm\amd64\CallDescrWorkerAMD64.asm @ 101] 
0e 0000004c`401e9d80 00007ffa`e055842a coreclr!CallDescrWorkerWithHandler+0x1de [e:\gh\gkhanna79\coreclr\src\vm\callhelpers.cpp @ 81] 
0f 0000004c`401e9e00 00007ffa`e004a377 coreclr!MethodDescCallSite::CallTargetWorker+0xdfa [e:\gh\gkhanna79\coreclr\src\vm\callhelpers.cpp @ 648] 
10 0000004c`401ea470 00007ffa`e042d201 coreclr!MethodDescCallSite::Call_RetOBJECTREF+0x127 [e:\gh\gkhanna79\coreclr\src\vm\callhelpers.h @ 436] 
11 0000004c`401ea570 00007ffa`e0549e8c coreclr!AppDomain::RaiseAssemblyResolveEvent+0x5e1 [e:\gh\gkhanna79\coreclr\src\vm\appdomain.cpp @ 10187] 
12 0000004c`401eac20 00007ffa`e043ee6a coreclr!AssemblySpec::ResolveAssemblyFile+0x4ec [e:\gh\gkhanna79\coreclr\src\vm\assemblyspec.cpp @ 709] 
13 0000004c`401eaeb0 00007ffa`e042af6c coreclr!AppDomain::TryResolveAssembly+0x7a [e:\gh\gkhanna79\coreclr\src\vm\appdomain.cpp @ 7388] 
14 0000004c`401eafb0 00007ffa`e03f7071 coreclr!AppDomain::PostBindResolveAssembly+0x31c [e:\gh\gkhanna79\coreclr\src\vm\appdomain.cpp @ 6792] 
15 0000004c`401eb150 00007ffa`e05476aa coreclr!AppDomain::BindAssemblySpec+0xee1 [e:\gh\gkhanna79\coreclr\src\vm\appdomain.cpp @ 7234] 
16 0000004c`401ebfb0 00007ffa`e054656b coreclr!AssemblySpec::LoadDomainAssembly+0x7ba [e:\gh\gkhanna79\coreclr\src\vm\assemblyspec.cpp @ 915] 
17 0000004c`401ec320 00007ffa`e09d50f5 coreclr!AssemblySpec::LoadAssembly+0x17b [e:\gh\gkhanna79\coreclr\src\vm\assemblyspec.cpp @ 732] 
18 0000004c`401ec440 00007ffa`de58b602 coreclr!AssemblyNative::Load+0x8a5 [e:\gh\gkhanna79\coreclr\src\vm\assemblynative.cpp @ 177] 
19 0000004c`401ecb40 00007ffa`de58cd92 System_Private_CoreLib!System.Reflection.RuntimeAssembly.nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMark ByRef, IntPtr, Boolean, Boolean, IntPtr)+0x82 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Reflection\RuntimeAssembly.cs @ 455] 
1a 0000004c`401ecbb0 00007ffa`de5a70fd System_Private_CoreLib!System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(System.String, System.Globalization.CultureInfo, System.Version, Boolean, System.Threading.StackCrawlMark ByRef)+0x172 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Reflection\RuntimeAssembly.cs @ 859] 
1b 0000004c`401eccb0 00007ffa`de5a5741 System_Private_CoreLib!System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(System.Globalization.CultureInfo, System.Threading.StackCrawlMark ByRef)+0x16d [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ManifestBasedResourceGroveler.cs @ 432] 
1c 0000004c`401ecf90 00007ffa`de4cbd6e System_Private_CoreLib!System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(System.Globalization.CultureInfo, System.Collections.Generic.Dictionary`2<System.String,System.Resources.ResourceSet>, Boolean, Boolean, System.Threading.StackCrawlMark ByRef)+0x1c1 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ManifestBasedResourceGroveler.cs @ 82] 
1d 0000004c`401ed0d0 00007ffa`de4cbadb System_Private_CoreLib!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo, Boolean, Boolean, System.Threading.StackCrawlMark ByRef)+0x26e [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ResourceManager.cs @ 692] 
1e 0000004c`401ed240 00007ffa`de4cd765 System_Private_CoreLib!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo, Boolean, Boolean)+0x8b [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ResourceManager.cs @ 652] 
1f 0000004c`401ed2a0 00007ffa`de4cd297 System_Private_CoreLib!System.Resources.ResourceManager.GetString(System.String, System.Globalization.CultureInfo)+0x4b5 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ResourceManager.cs @ 1158] 
20 0000004c`401ed470 00007ffa`81420ff1 System_Private_CoreLib!System.Resources.ResourceManager.GetString(System.String)+0x47 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ResourceManager.cs @ 1088] 
21 0000004c`401ed4b0 00007ffa`e0911a43 P2_Repro!temp.Program.Main(System.String[])+0x231
22 0000004c`401ed5c0 00007ffa`e055761e coreclr!CallDescrWorkerInternal+0x83 [E:\GH\gkhanna79\coreclr\src\vm\amd64\CallDescrWorkerAMD64.asm @ 101] 
23 0000004c`401ed600 00007ffa`e055842a coreclr!CallDescrWorkerWithHandler+0x1de [e:\gh\gkhanna79\coreclr\src\vm\callhelpers.cpp @ 81] 
24 0000004c`401ed680 00007ffa`e004a133 coreclr!MethodDescCallSite::CallTargetWorker+0xdfa [e:\gh\gkhanna79\coreclr\src\vm\callhelpers.cpp @ 648] 
25 0000004c`401edcf0 00007ffa`e01bfcda coreclr!MethodDescCallSite::Call+0x23 [e:\gh\gkhanna79\coreclr\src\vm\callhelpers.h @ 433] 
26 0000004c`401edd20 00007ffa`e01bfe25 coreclr!``RunMain'::`22'::__Body::Run'::`5'::__Body::Run+0x24a [e:\gh\gkhanna79\coreclr\src\vm\assembly.cpp @ 1849] 
27 0000004c`401eded0 00007ffa`e01c011e coreclr!`RunMain'::`22'::__Body::Run+0x85 [e:\gh\gkhanna79\coreclr\src\vm\assembly.cpp @ 1862] 
28 0000004c`401edf50 00007ffa`e01b6b22 coreclr!RunMain+0x18e [e:\gh\gkhanna79\coreclr\src\vm\assembly.cpp @ 1862] 
29 0000004c`401edff0 00007ffa`e004e868 coreclr!Assembly::ExecuteMainMethod+0x412 [e:\gh\gkhanna79\coreclr\src\vm\assembly.cpp @ 1944] 
2a 0000004c`401ee4b0 00007ffa`dff96594 coreclr!CorHost2::ExecuteAssembly+0x508 [e:\gh\gkhanna79\coreclr\src\vm\corhost.cpp @ 501] 
2b 0000004c`401ee780 00007ffa`f11fe739 coreclr!coreclr_execute_assembly+0x124 [e:\gh\gkhanna79\coreclr\src\dlls\mscoree\unixinterface.cpp @ 407] 
2c 0000004c`401ee840 00007ffa`f11fecc4 hostpolicy+0x1e739
2d 0000004c`401eef10 00007ffb`2aa59b05 hostpolicy!corehost_main+0x164
2e 0000004c`401ef090 00007ffb`2aa5f42b hostfxr+0x19b05
2f 0000004c`401ef160 00007ffb`2aa5e819 hostfxr!hostfxr_resolve_sdk+0x577b
30 0000004c`401ef800 00007ffb`2aa5cc8d hostfxr!hostfxr_resolve_sdk+0x4b69
31 0000004c`401ef990 00007ff7`fc079abc hostfxr!hostfxr_resolve_sdk+0x2fdd
32 0000004c`401efb20 00007ff7`fc07e099 dotnet+0x9abc
33 0000004c`401efc30 00007ffb`3b472774 dotnet+0xe099
34 0000004c`401efc70 00007ffb`3c3a0d61 KERNEL32!BaseThreadInitThunk+0x14 [base\win32\client\thread.c @ 64] 
35 0000004c`401efca0 00000000`00000000 ntdll!RtlUserThreadStart+0x21 [minkernel\ntdll\rtlstrt.c @ 997] 

@gkhanna79
Copy link
Member Author

@tarekgh The implementation indicates that managed resolve event handlers can throw and their exceptions need to be propagated (which is what is happening in the bug). If we go via that logic, the fix should be in one of the following frames (perhaps 1b since it already has try/catch for other scenarios when failing to resolve satellite assemblies):

1a 0000004c`401ecbb0 00007ffa`de5a70fd System_Private_CoreLib!System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(System.String, System.Globalization.CultureInfo, System.Version, Boolean, System.Threading.StackCrawlMark ByRef)+0x172 [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Reflection\RuntimeAssembly.cs @ 859] 
1b 0000004c`401eccb0 00007ffa`de5a5741 System_Private_CoreLib!System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(System.Globalization.CultureInfo, System.Threading.StackCrawlMark ByRef)+0x16d [E:\GH\gkhanna79\coreclr\src\mscorlib\src\System\Resources\ManifestBasedResourceGroveler.cs @ 432] 

What do you and @jkotas think about this?

@gkhanna79
Copy link
Member Author

Looking at https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs#L426, it seems to me that the fix should be in ManifestBasedResourceGroveler. Would you both agree since it allows the exception propagation, as expected, and also line up with the scenarios that function handles?

@jkotas
Copy link
Member

jkotas commented Jun 16, 2017

all my point is I am trying to see if there is a way to avoid throwing and then catching

When the OnAssemblyResolveEvent runs, we have thrown and caught at least one exception already - the OnAssemblyResolveEvent runs in the catch handler as the last resort.

@jkotas
Copy link
Member

jkotas commented Jun 16, 2017

The implementation indicates that managed resolve event handlers can throw and their exceptions need to be propagated

It can throw exceptions like out of memory, and those should propagate.

If it cannot find what it is asked to find, it should return null - not throw.

@tarekgh
Copy link
Member

tarekgh commented Jun 16, 2017

one more question regarding the method nLoad

RuntimeAssembly retAssembly = nLoad(an, null, this, ref stackMark,

This method takes a parameter throwOnFileNotFound, and I think it should respect this parameter but this is not happening. I am seeing nLoad is called in 2 places, the first is from InternalGetSatelliteAssembly and I think your fix will address that. But I am seeing it is called from InternalLoadAssemblyName too and I think there will be a problem there for anyone calling it with throwOnFileNotFound=false and then nLoad eventually throw FileNotFound

@gkhanna79
Copy link
Member Author

It can throw exceptions like out of memory, and those should propagate

The documentation does not indicate so - it simply says valid or null reference back. That said, if there was another handler registered for AssemblyResolve, prior to LoadFrom, and it throws an exception, we will landup with this issue.

@gkhanna79
Copy link
Member Author

@tarekgh That parameter gets respected unless we are in the fallback mode to invoke AssemblyResolve event against AppDomain (which is what is happening in this issue).

@tarekgh
Copy link
Member

tarekgh commented Jun 16, 2017

That parameter gets respected unless we are in the fallback mode to invoke AssemblyResolve event against AppDomain (which is what is happening in this issue).

Is it possible InternalLoadAssemblyName get called in the same fallback mode? if so then this code path has the same problem similar to what we are fixing here. I maybe missing something here.

@gkhanna79
Copy link
Member Author

@tarekgh and I chatted offline and I explained how the fix works as well.

@jkotas Does this look good to you as well?

@jkotas
Copy link
Member

jkotas commented Jun 16, 2017

The documentation does not indicate so - it simply says valid or null reference back

Exception for fatal errors can be thrown anywhere. The documentation does not explicitly mentions them.

It think it would be better for this to catch FileNotFoundException only. But if you have a good reason for it to catch everything, I can live with it.

@gkhanna79
Copy link
Member Author

@jkotas I was thinking about it more and I agree - FNF maps to missing file and is okay to be returned as null. Everything else should get propagated.

I will make the change.

@gkhanna79
Copy link
Member Author

@jkotas Updated to catch only FNF.

@gkhanna79
Copy link
Member Author

@dotnet-bot test OSX10.12 x64 Checked Build and Test please

@gkhanna79
Copy link
Member Author

@mmitche Is the OSX failure a known issue (see https://ci.dot.net/job/dotnet_coreclr/job/master/job/checked_osx10.12_flow_prtest/4079/consoleFull#-1637969066ee26338-6221-4f7c-8c8f-1d1d5cb4704a):

ERROR: [WS-CLEANUP] Cannot delete workspace: remote file operation failed: /Users/dotnet-bot/j/workspace/dotnet_coreclr/master/checked_osx10.12_flow_prtest at hudson.remoting.Channel@434661e9:dci-mac-build-048: hudson.remoting.ChannelClosedException: channel is already closed

@gkhanna79
Copy link
Member Author

@dotnet-bot test OSX10.12 x64 Checked Build and Test please

@mmitche
Copy link
Member

mmitche commented Jun 16, 2017

@gkhanna79 Network issues

@gkhanna79
Copy link
Member Author

@mmitche Is this latest attempt to rerun the leg also an infra issue?

@mmitche
Copy link
Member

mmitche commented Jun 16, 2017

cc @dotnet/dnceng
Yes, anytime you see "Channel is already closed" in whatever context, it is always an infra issue.

You can take the offending machine offline, otherwise they tend to eat runs for a few mins.

@mmitche
Copy link
Member

mmitche commented Jun 16, 2017

@dotnet-bot test OSX10.12 x64 Checked Build and Test

@gkhanna79 gkhanna79 merged commit 27e625f into dotnet:master Jun 17, 2017
@karelz karelz added this to the 2.1.0 milestone Aug 28, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
6 participants