Bug 17010 - System.ExecutionEngineException when reflecting a class with a static constructor and non-resolvable instance type
Summary: System.ExecutionEngineException when reflecting a class with a static constru...
Status: REOPENED
Alias: None
Product: Runtime
Classification: Mono
Component: Reflection (show other bugs)
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-01-01 07:05 UTC by Alistair Bush
Modified: 2017-10-14 00:20 UTC (History)
4 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Reproduction project (6.55 MB, application/x-xz)
2014-01-01 07:19 UTC, Alistair Bush
Details
possible patch to solve this issue (1.14 KB, patch)
2014-01-04 19:37 UTC, Alistair Bush
Details | Diff
use MonoClass->inited to attempt to determine when the fast method can be called. (1.29 KB, patch)
2014-01-04 20:36 UTC, Alistair Bush
Details | Diff

Description Alistair Bush 2014-01-01 07:05:06 UTC
I am working on getting fubumvc running on linux/mono and have encounter the following issue.  
This issue DOES NOT exist on windows .NET

I have replicated this on

$ mono --version
Mono Runtime Engine version 3.2.7 (branch-master/87e820d Tue Dec 31 14:09:49 NZDT 2013)
Copyright (C) 2002-2013 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug 
        LLVM:          supported, not enabled.
        GC:            sgen


*********** Description *************

When loading Assemblies into an AppDomain and then invoking methods on the Types of those assemblies then if a type defined in a missing dll is defined as an instance variable of the class of that type then you will receive the  error message [1].   At no point have I attempted to initalise the Type yet mono is still attempting to resolve the missing types.

You may see the attached project as an example.


[1] Example error messages
1) When: var setup = new AppDomainSetup {
	ApplicationName = "Bottle-Services-AppDomain",
	ShadowCopyFiles = "true",

Then

System.ExecutionEngineException: Failed to create shadow copy (CopyFile).
  at (wrapper managed-to-native) System.Type:type_is_assignable_from (System.Type,System.Type)
  at System.Type.IsAssignableFrom (System.Type c) [0x00096] in /var/tmp/paludis/dev-lang-mono-9999/work/mono-9999/mcs/class/corlib/System/Type.cs:970 
  at AssemblyTypeListTest.Proxy.Go () [0x00142] in /home/alistair/Projects/TopshelfTest/AssemblyTypeListTest/Running/Proxy.cs:48


2) When: var setup = new AppDomainSetup {
	ApplicationName = "Bottle-Services-AppDomain",
	ShadowCopyFiles = "false",

Then:

System.IO.FileNotFoundException: Could not load file or assembly 'WebDriver, Version=2.37.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
File name: 'WebDriver, Version=2.37.0.0, Culture=neutral, PublicKeyToken=null'
  at (wrapper managed-to-native) System.Type:type_is_assignable_from (System.Type,System.Type)
  at System.Type.IsAssignableFrom (System.Type c) [0x00096] in /var/tmp/paludis/dev-lang-mono-9999/work/mono-9999/mcs/class/corlib/System/Type.cs:970 
  at AssemblyTypeListTest.Proxy.Go () [0x00142] in /home/alistair/Projects/TopshelfTest/AssemblyTypeListTest/Running/Proxy.cs:48
Comment 1 Alistair Bush 2014-01-01 07:19:51 UTC
Created attachment 5742 [details]
Reproduction project
Comment 2 Zoltan Varga 2014-01-04 06:32:59 UTC
When the runtime detects missing assemblies/types is an implementation detail. Mono detects them more aggressively than MS.NET, so some types become unusable which are usable under MS.
Comment 3 Alistair Bush 2014-01-04 19:37:32 UTC
Created attachment 5761 [details]
possible patch to solve this issue

I have noticed that there are 2 implementation,  mono_class_is_assignable_from and mono_class_is_assignable_from_slow

This patch changes the code to not init the given types and instead call the _slow method.  My very limited testing suggests that this is change will resolve this particular issue.

Would you know if there is any real difference between these 2 methods, besides performance?

Does the MonoClass struct of this type have the inited bool as true under 'normal' use cases?  My thinking is that we could call the _slow method for klass.inited==false types but the faster 'non-slow' method once the types have actually been loaded.
Comment 4 Alistair Bush 2014-01-04 20:36:41 UTC
Created attachment 5762 [details]
use MonoClass->inited to attempt to determine when the fast method can be called.

To drive the point home, how about a patch to demonstrate.

I haven't tested this in anyway but this should give the best of both worlds.
Comment 5 Alistair Bush 2014-01-05 00:57:48 UTC
I have created a branch https://github.com/alistair/mono/tree/mono_is_assignable_from_fix_option2 which has a better implementation of the second patch here.

I haven't tested this yet, which is why I haven't created a pull request.

Does this seem like a possible solution?
Why does mono detect these issues more aggressively than MS.NET, is it by design? and what about the affect this might have as in this case? (e.g. a library which deliberately does not include all libraries as it knowns it doesn't need to in MS.NET.
Comment 6 Zoltan Varga 2014-01-05 04:35:29 UTC
Where broken types are detected is an implementation detail, and programs shouldn't depend on it.
Comment 7 Alistair Bush 2014-01-05 05:36:18 UTC
Cool so does this mean the bug is invalid?  

And how does this explain the difference in behavior of System.Type.IsAssignableFrom between .net and mono? Especially seeing that other System.Type functional works as expected against a non-fully resolved type?

I would expect that mono would attempt to implement IsAssignableFrom to behave the same as .net.  especially seeing you already have the code to do so.

It should also be noted that I'm not interested in the broken type and have no intention of ever creating an instance of that type either directly or indirectly. It is only that I am iterating over all types that u come across this one.
Comment 8 Zoltan Varga 2014-01-05 10:55:28 UTC
The handling of broken types is not documented, so its hard to decide how to handle them, esp. without complicating the already complicated runtime metadata code. If somebody wants to process assemblies which have missing dependencies, it can be done using Cecil or IKVM.Reflection.
Comment 9 Rodrigo Kumpera 2014-01-08 18:09:07 UTC
Each operation requires a different parts of the internal metadata the runtime generates.

The slow version of the type test operations are not meant for general consumption as they cut some corners compared to the fast version that will lead to invalid results.

I committed to master a version that makes type checking lazier, hopefully enough to match MS closer.
If that version is not enough, then we'll have to find a more creative solution.
Comment 10 Rodrigo Kumpera 2014-01-12 01:44:51 UTC
I had to revert the fix as it broke other parts of the runtime (the WCF test suite).
Comment 11 Rodrigo Kumpera 2017-10-14 00:20:56 UTC
CC'ing Aleksey. This bug shows another case where mono is not as lazy as the CLR.

Note You need to log in before you can comment on or make changes to this bug.