Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assertion failed in assemblybinder.cpp, line 1833 #6163

Closed
tmat opened this issue Jun 16, 2016 · 6 comments
Closed

Assertion failed in assemblybinder.cpp, line 1833 #6163

tmat opened this issue Jun 16, 2016 · 6 comments

Comments

@tmat
Copy link
Member

tmat commented Jun 16, 2016

When loading analyzer assemblies on CoreCLR on Mac/Linux we hit a segmentation fault. Running on the debug build of the Core CLR from master reports an assert:

debug build

Assert failure(PID 39717 [0x00009b25], Thread: 306271 [0x4ac5f]): pLoadedAssembly != NULL
    File: /Users/tomat/coreclr/src/binder/assemblybinder.cpp Line: 1833
    Image: /Users/tomat/roslyn2/Binaries/Bootstrap/corerun

**** MessageBox invoked, title 'corerun - Assert Failure (PID 39717, Thread 306271/0x4ac5f)' ****
  pLoadedAssembly != NULL

/Users/tomat/coreclr/src/binder/assemblybinder.cpp, Line: 1833

Abort - Kill program
Retry - Debug
Ignore - Keep running


Image:
/Users/tomat/roslyn2/Binaries/Bootstrap/corerun

********

Abort trap: 6

release build:

thread dotnet/coreclr#1: tid = 0x37fa9, 0x0000000101439fc3 libcoreclr.dylib`CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName*, ICLRPrivAssembly**) + 467, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x60)
  * frame #0: 0x0000000101439fc3 libcoreclr.dylib`CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName*, ICLRPrivAssembly**) + 467
    frame dotnet/coreclr#1: 0x0000000101119e47 libcoreclr.dylib`AssemblySpec::Bind(AppDomain*, int, CoreBindResult*, int, int, StackCrawlMark*) + 1639
    frame dotnet/coreclr#2: 0x00000001010cbe70 libcoreclr.dylib`AppDomain::BindAssemblySpec(AssemblySpec*, int, int, StackCrawlMark*, AssemblyLoadSecurity*, int) + 416
    frame dotnet/coreclr#3: 0x0000000101212200 libcoreclr.dylib`PEFile::LoadAssembly(unsigned int, IMDInternalImport*, char const*, char const*) + 352
    frame dotnet/coreclr#4: 0x00000001010ee72a libcoreclr.dylib`Module::LoadAssembly(AppDomain*, unsigned int, char const*, char const*) + 346
    frame dotnet/coreclr#5: 0x00000001010de296 libcoreclr.dylib`Assembly::FindModuleByTypeRef(Module*, unsigned int, Loader::LoadFlag, int*) + 390
    frame dotnet/coreclr#6: 0x000000010110253f libcoreclr.dylib`ClassLoader::LoadTypeDefOrRefThrowing(Module*, unsigned int, ClassLoader::NotFoundAction, ClassLoader::PermitUninstantiatedFlag, unsigned int, ClassLoadLevel) + 383
    frame dotnet/coreclr#7: 0x0000000101103224 libcoreclr.dylib`ClassLoader::LoadApproxParentThrowing(Module*, unsigned int, SigPointer*, SigTypeContext const*) + 116
    frame dotnet/coreclr#8: 0x0000000101318dfe libcoreclr.dylib`ClassLoader::CreateTypeHandleForTypeDefThrowing(Module*, unsigned int, Instantiation, AllocMemTracker*) + 462
    frame dotnet/coreclr#9: 0x00000001011037f0 libcoreclr.dylib`ClassLoader::CreateTypeHandleForTypeKey(TypeKey*, AllocMemTracker*) + 1040
    frame dotnet/coreclr#10: 0x000000010110331a libcoreclr.dylib`ClassLoader::DoIncrementalLoad(TypeKey*, TypeHandle, ClassLoadLevel) + 74
    frame dotnet/coreclr#11: 0x0000000101104380 libcoreclr.dylib`ClassLoader::LoadTypeHandleForTypeKey_Body(TypeKey*, TypeHandle, ClassLoadLevel) + 1328
    frame dotnet/coreclr#12: 0x00000001011003a4 libcoreclr.dylib`ClassLoader::LoadTypeHandleForTypeKey(TypeKey*, TypeHandle, ClassLoadLevel, InstantiationContext const*) + 180
    frame dotnet/coreclr#13: 0x00000001011017b5 libcoreclr.dylib`ClassLoader::LoadTypeDefThrowing(Module*, unsigned int, ClassLoader::NotFoundAction, ClassLoader::PermitUninstantiatedFlag, unsigned int, ClassLoadLevel, Instantiation*) + 581
    frame dotnet/coreclr#14: 0x00000001010fe13e libcoreclr.dylib`ClassLoader::LoadTypeHandleThrowing(NameHandle*, ClassLoadLevel, Module*) + 702
    frame dotnet/coreclr#15: 0x0000000101385e4c libcoreclr.dylib`TypeName::GetTypeHaveAssemblyHelper(Assembly*, int, int, Object**, int) + 492
    frame dotnet/coreclr#16: 0x0000000101383582 libcoreclr.dylib`TypeName::GetTypeWorker(int, int, int, Assembly*, int, int, StackCrawlMark*, Assembly*, ICLRPrivBinder*, int, Object**) + 306
    frame dotnet/coreclr#17: 0x000000010138459a libcoreclr.dylib`TypeName::GetTypeManaged(char16_t const*, DomainAssembly*, int, int, int, int, StackCrawlMark*, int, Object**, ICLRPrivBinder*) + 346
    frame dotnet/coreclr#18: 0x0000000101280153 libcoreclr.dylib`AssemblyNative::GetType(QCall::AssemblyHandle, char16_t const*, int, int, QCall::ObjectHandleOnStack, QCall::ObjectHandleOnStack) + 163
    frame dotnet/coreclr#19: 0x000000010791e1a4
    frame dotnet/coreclr#20: 0x000000010792bc18
    frame dotnet/coreclr#21: 0x000000010958d564
    frame dotnet/coreclr#22: 0x000000010958d431
    frame dotnet/coreclr#23: 0x000000010958d139
    frame dotnet/coreclr#24: 0x00000001094d1d7f
    frame dotnet/runtime#3858: 0x000000010939912c
    frame dotnet/runtime#3859: 0x0000000108559f92
    frame dotnet/coreclr#27: 0x000000010939f1cb
    frame dotnet/runtime#3860: 0x000000010939ecb6
    frame dotnet/runtime#3861: 0x0000000107e685b9
    frame dotnet/runtime#3862: 0x0000000107e67bfe
    frame dotnet/runtime#3863: 0x0000000107e678d7
    frame dotnet/coreclr#32: 0x0000000107e64e33
    frame dotnet/runtime#3864: 0x0000000107e6536b
    frame dotnet/runtime#3865: 0x0000000107e66e33
    frame dotnet/coreclr#35: 0x0000000107e65275
    frame dotnet/coreclr#36: 0x0000000107e650ed
    frame dotnet/runtime#3866: 0x000000010139bcda libcoreclr.dylib`FastCallFinalizeWorker_End + 124
    frame dotnet/coreclr#38: 0x000000010128b0b5 libcoreclr.dylib`MethodDescCallSite::CallTargetWorker(unsigned long const*) + 853
    frame dotnet/runtime#3867: 0x00000001010df91a libcoreclr.dylib`RunMain(MethodDesc*, short, int*, PtrArray**) + 938
    frame dotnet/runtime#3868: 0x00000001010dfadd libcoreclr.dylib`Assembly::ExecuteMainMethod(PtrArray**, int) + 221
    frame dotnet/coreclr#41: 0x000000010111bfe3 libcoreclr.dylib`CorHost2::ExecuteAssembly(unsigned int, char16_t const*, int, char16_t const**, unsigned int*) + 435
    frame dotnet/coreclr#42: 0x0000000101050953 libcoreclr.dylib`coreclr_execute_assembly + 259
    frame dotnet/runtime#3869: 0x0000000100001f8b corerun`ExecuteManagedAssembly(char const*, char const*, char const*, int, char const**) + 1195
    frame dotnet/runtime#3870: 0x00000001000013bb corerun`corerun(int, char const**) + 395
    frame dotnet/runtime#3871: 0x00007fff877595c9 libdyld.dylib`start + 1
@tmat
Copy link
Member Author

tmat commented Jun 16, 2016

@gkhanna79 @jkotas

@gkhanna79
Copy link
Member

gkhanna79 commented Jun 17, 2016

If an app has a static assembly reference to an assembly that is missing (which is not the normal case since .NET Core app have their dependencies complete) OR attempts to do Assembly.Load against an assembly that is missing AND has wired up to the Resolving event to load the assemblies from custom locations, then the event will not return a valid reference and could result in a crash.

The workaround to address the above problem is one of the following:

Load the assembly using LoadFromAssemblyName instead of Assembly.Load, OR
Create a custom AssemblyLoadContext and override its Load method to resolve the assembly.

@gkhanna79
Copy link
Member

@tmat Given that there are two workarounds, this should not be blocking until the formal fix comes through. Does that sound good to you?

@tmat
Copy link
Member Author

tmat commented Jun 17, 2016

@gkhanna79 Sounds good.

@gkhanna79
Copy link
Member

Reopening until tests are updated as well.

@gkhanna79 gkhanna79 reopened this Jun 17, 2016
@gkhanna79
Copy link
Member

Test added in CoreFX via dotnet/corefx#9639

dotnet-bot referenced this issue in dotnet-bot/coreclr Aug 7, 2016
gkhanna79 referenced this issue in dotnet-bot/coreclr Aug 8, 2016
gkhanna79 referenced this issue in dotnet-bot/coreclr Aug 8, 2016
lstratman referenced this issue in medicomp/edge Aug 23, 2016
We are required to preload System.Runtime.Serialization.Primitives since
it is used for serialization by Newtonsoft.Json.  Failure to do so
results in an EngineExecutionException because of
https://github.com/dotnet/coreclr/issues/5837, which should be fixed in
a post-RTM release.
tmeschter referenced this issue in tmeschter/msbuild Aug 25, 2016
Related to issue dotnet#750.

We need the ability to load task-containing assemblies from arbitrary
locations on disk determined at run time, along with thei dependencies.
It is assumed that their dependencies will be located next to them in
the file system, or in some well-known location.

Ideally we would handle the dependencies by hooking the `Resolving`
event on the default `AssemblyLoadContext`. However, due to
https://github.com/dotnet/coreclr/issues/5837 we can't currently do
this. Instead, we need to implement our own `AssemblyLoadContext`.

This is what we currently do. However, we run into a problem when a task
assembly depends on, say, Microsoft.Build.dll (which is pretty much
guaranteed). Microsoft.Build will already be loaded into the default
`AssemblyLoadContext`, but since our task assembly was loaded into *our*
context, we are likely to be asked to load it again when the task needs
it. We currently handle this by looking for it in the app's base
directory, which seems like a good bet.

So we may end up loading this assembly twice, in two different
contexts--not great, but everything still works. Issue dotnet#750 comes into
play when Microsoft.Build.dll has been CrossGen'd to a native assembly.
Both contexts will find and try to load the native assembly--and this is
currently not allowed.

So to work around these other issues in assembly loading, we need to
maintain our own `AssemblyLoadContext` for the time being. However, we
now ask the default `AssemblyLoadContext` to first try satisfying the
load. If it succeeds, the load will occur in that context. Only if it
can't find the assembly in question do we attempt to find and load the
assembly ourselves (putting it in our context).
tmeschter referenced this issue in tmeschter/msbuild Aug 29, 2016
Related to issue dotnet#750.

We need the ability to load task-containing assemblies from arbitrary
locations on disk determined at run time, along with their dependencies.
It is assumed that their dependencies will be located next to them in
the file system, or in some well-known location.

Ideally we would handle the dependencies by hooking the `Resolving`
event on the default `AssemblyLoadContext`. However, due to
https://github.com/dotnet/coreclr/issues/5837 we can't currently do
this. Instead, we need to implement our own `AssemblyLoadContext`.

Indeed, this is what we currently do. However, we run into a problem when
a task assembly depends on, say, Microsoft.Build.dll (which is pretty much
guaranteed). Microsoft.Build will already be loaded into the default
`AssemblyLoadContext`, but since our task assembly was loaded into *our*
context, we are likely to be asked to load it again when the task needs
it. We currently handle this by looking for it in the app's base
directory, which seems like a good bet.

So we may end up loading this assembly twice, in two different
contexts--not great, but everything still works. Issue dotnet#750 comes into
play when Microsoft.Build.dll has been CrossGen'd to a native assembly.
Both contexts will find and try to load the native assembly--and this is
currently not allowed.

So to work around these other issues in assembly loading, we need to
maintain our own `AssemblyLoadContext` for the time being. However, we
now ask the default `AssemblyLoadContext` to first try satisfying the
load. If it succeeds, the load will occur in that context.

If it fails, we'll get an exception. Either the default context couldn't
locate an assembly with the given name, or located what *should* have
been the assembly but wasn't actually (e.g., a native file with the same
name, or a corrupted file) or may couldn't read the file due to
permission issues. If this occurs, we simply catch and swallow the
exception, and then attempt to find and load the assembly ourselves,
putting it in our context.

We could think about letting some of these through. For example, if the
default context located the assembly but couldn't read it
(BadImageFormatException or an exception representing a permission issue)
then it would probably be better to let that exception propagate rather
than catch or ignore it. It's not clear where we would draw the line,
though, and since this whole approach is a workaround for other runtime
issues I'd rather just keep it as simple as possible.
tmeschter referenced this issue in tmeschter/msbuild Oct 3, 2016
The only reason we implemented our own `AssemblyLoadContext` was to work around https://github.com/dotnet/coreclr/issues/5837. That bug prevented us from helping the default `AssemblyLoadContext` find assemblies by hooking the `Resolving` event; the only other way to get them loaded was to do it ourselves.

This workaround has its own problems. Since we've got two different load contexts, it is entirely possible that the same assembly will be loaded twice: once in each. That isn't great, but it works--except for crossgen'd assemblies due to https://github.com/dotnet/coreclr/issues/6695. For performance reasons, the dotnet CLI crossgens many if not all of the assemblies it loads, so it runs into problems all the time.

So now that https://github.com/dotnet/coreclr/issues/5837 is fixed we can simplify things by getting rid of our `AssemblyLoadContext` and simply hooking the `Resolving` event. This will avoid double loads and thus avoid https://github.com/dotnet/coreclr/issues/6695.
@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the 1.1.x milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants