Closed globeport closed 6 years ago
Not sure what's going on but it looks like some component is trying to load libuv.dll (a native component) via reflection only load. I assume this is just a first chance exception?
Yes, the Orleans client functions correctly following initialization despite these errors.
On startup, the Orleans client searches for grain interfaces using reflection. That's normal behavior. Sometimes a DLL load may fail, in these cases the error is logged.
We are looking to add an option to avoid blind scanning of binaries, but this is the current 'by design' behavior.
Ok thanks. It would definitely be nice to have some hooks to control the assembly scan.
@globeport Feel free to suggest what the hooks should look like.
With the code-based configuration, could it just be a delegate? Say, Func<IEnumerable<string>>
where every entry is the full path of the assembly to scan? That would allow for both static assembly lists and finding them at runtime.
var config = new ClusterConfiguration();
config.Defaults.AssemblyListProvider = () => {
return new List<string>()
{
"C:/Foo/bar.dll"
};
};
Not sure how this works out with xml-based configurations...
I think we can solve this by smartening the loader by checking the PE Header in the binaries using Kirill Osenkov's answer here at SO: http://stackoverflow.com/questions/367761/how-to-determine-whether-a-dll-is-a-managed-assembly-or-native-prevent-loading
Which points to: http://apichange.codeplex.com/SourceControl/changeset/view/76c98b8c7311#ApiChange.Api/src/Introspection/CorFlagsReader.cs
What do you think?
@TrexinanF14 I'm concerned full paths may be a problem, especially in case Azure Cloud Services. Why not just assembly names?
@attilah It would really help indeed to auto-skip non-managed dlls.
@sergeybykov Yeah, scratch the full path requirement, although it seems that accepting relative paths would be a good idea (relative based on the location of the executing assembly?). Or some other method to look outside the default directories.
Should this conversation hop over to #1852? It seems like the solution provided by @attilah would solve this issue.
Based on the CorFlagsReader above I wrote this snippet and tested on major windows directories on my system, seems to work ok. What was got to assembly loading that was loaded properly!
try
{
var flags = default(CorFlagsReader);
// Use stream to have least access required for Assembly loading
using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
flags = CorFlagsReader.ReadAssemblyMetadata(stream);
}
if (flags != null)
{
var isManaged = flags.IsPureIL || flags.ProcessorArchitecture == ProcessorArchitecture.MSIL;
var isProcessorArchitectureMatching =
(Environment.Is64BitProcess && flags.ProcessorArchitecture == ProcessorArchitecture.Amd64) ||
(!Environment.Is64BitProcess && flags.ProcessorArchitecture == ProcessorArchitecture.X86);
if (isManaged && isProcessorArchitectureMatching)
{
// At this point the file is "safe" to load
// user specific predicate can be called here if we'd like to support blacklisting too.
}
}
}
catch (IOException)
{
}
catch (UnauthorizedAccessException)
{
}
BadImageFormatException is not needed to check here, since no assembly loading happens here, but access errors can happen.
What is the current behavior for the exceptions above?
If be happy if there was a switch in the configuration to enable/disable automatic scanning of assemblies. If enabled, I'd like to be able to exclude specific assemblies by name. If disabled, I'd like to be able to include specific assemblies by name. It would also be nice to be able to override this behaviour in code and supply an array of assemblies that can be located via reflection. I'm unclear why there would be a requirement to include assemblies by their path (relative or absolute)?
@sergeybykov, it might seem like a basic question, well... I guess it is: does the Orleans client have to to scan the assemblies on initialization? Is there a technical limitation that prevents it from applying the Orleans magic dynamically to assemblies as they're loaded ?
@globeport Couldn't we achieve both goals by turning off scanning when an explicit list of application assemblies is provided? Otherwise, scan like we do today. We'd still need to load Orleans assemblies regardless, of course.
@shayhatsor The reason Orleans client scans assemblies IIRC is for stream providers. We might be able to do away with that because providers are explicitly defined in config.
Sure, sorry I was thinking that it would be nice to exclude problem assemblies, but if the scan is updated to exclude native assemblies then its probably not required. Providing a single include list to override automatic scanning (via the configuration file or via code) would be perfect.
Closing this, as we don't scan all assemblies by default in 2.0.0.
I'm getting the following output running Orleans from an asp.net core app... (.Net Framwork 4.6.1) The application runs successfully beyond this.
[2016-06-14 13:25:23.041 GMT 6 ERROR 101716 AssemblyLoader.Client ] !!!!!!!!!! An unexpected exception occurred while attempting to load an assembly.b0(Assembly assembly, IEnumerable`1& assemblyComplaints)
--- End of inner exception stack trace ---
at Orleans.Runtime.Utils.Flatten(ReflectionTypeLoadException rtle)
at Orleans.Runtime.AssemblyLoaderReflectionCriterion.<>cDisplayClass3_0.b 0(Assembly assembly, IEnumerableb__0(Assembly assembly, IEnumerable`1& assemblyComplaints)<---
...
...
---> (Inner Exception #1) System.TypeLoadException: Could not load type 'System.Object' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' because the parent does not exist.<---
---> (Inner Exception #2) System.TypeLoadException: Could not load type 'System.Object' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' because the parent does not exist.<---
...
...
Exc level 0: System.BadImageFormatException: Could not load file or assembly 'file:///C:\Tentacle\Applications\Test\WebApi\0.1.20160614.2_1\libuv.dll' or one of its dependencies. The module was expected to contain an assembly manifest. at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark) at System.Reflection.Assembly.ReflectionOnlyLoadFrom(String assemblyFile) at Orleans.Runtime.AssemblyLoader.ReflectionOnlyLoadAssembly(String pathName, Assembly& assembly, String[]& complaints) A ReflectionTypeLoadException has been thrown. The original exception and the contents of the LoaderExceptions property have been aggregated for your convenience. Exception = System.AggregateException: A ReflectionTypeLoadException has been thrown. The original exception and the contents of the LoaderExceptions property have been aggregated for your convenience. ---> System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) at System.Reflection.RuntimeAssembly.get_DefinedTypes() at Orleans.Runtime.AssemblyLoaderReflectionCriterion.<>cDisplayClass3_0.
1& assemblyComplaints) at Orleans.Runtime.AssemblyLoaderCriterion.EvaluateCandidate(Object input, IEnumerable
1& complaints) at Orleans.Runtime.AssemblyLoader.ShouldLoadAssembly(String pathName) ---> (Inner Exception #0) System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) at System.Reflection.RuntimeAssembly.get_DefinedTypes() at Orleans.Runtime.AssemblyLoaderReflectionCriterion.<>c__DisplayClass3_0.Hosting environment: Production Content root path: C:\Tentacle\Applications\Test\WebApi\0.1.20160614.2_1 Now listening on: http://localhost:4306/ Application started. Press Ctrl+C to shut down.