Bug 30488

Summary: [XI 8.10.1] "Error setting up QueryLanguage class vtable" during AOT of Rx-Linq assembly, related to the linker removing certain methods from the QueryLanguage class
Product: iOS Reporter: Brendan Zagaeski (Xamarin Support) <brendan.zagaeski>
Component: GeneralAssignee: Bugzilla <bugzilla>
Status: VERIFIED FIXED    
Severity: normal CC: kent.boogaart, mohitk, mono-bugs+monotouch, rolf, sebastien
Priority: ---    
Version: XI 8.10   
Target Milestone: Untriaged   
Hardware: PC   
OS: Mac OS   
Tags: Is this bug a regression?: ---
Last known good build:
Attachments: Test case
Diagnostic build output and version info

Description Brendan Zagaeski (Xamarin Support) 2015-05-26 23:46:40 UTC
Created attachment 11350 [details]
Test case

[XI 8.10.1] "Error setting up QueryLanguage class vtable" during AOT of Rx-Linq assembly because the linker removes the QueryLanguage class


I am not certain that this error should _not_ require user intervention. (Presumably the "System.Reactive.Linq" assembly has _not_ been audited by its authors for compatibility with the Xamarin.iOS linker.) But I also did not find any existing documentation about how to resolve this error message. If nothing else this bug report can serve as some small documentation about the error message.




## Regression status: technically it's a regression in XI 8.10.1 compared to 8.10.0, but it's a slightly unusual case.


The specific error message _itself_ is new [1] in XI 8.10.1 compared to XI 8.10.0.267 (6481535).

> [1] https://github.com/mono/mono/commit/e5678fa983d8b01d2ba5f91bcee364e42b0feea9


But perhaps that error message is simply exposing a case that _failed silently_ before XI 8.10.1?




## Steps to reproduce

Attempt to build the attached test case in the "Release|iPhone" configuration.


### About the test case

The test case is just a template iOS project with the following changes:

- Set the linker to link all assemblies in the Release configuration.

- Add the Rx-Linq NuGet package. 

- Add a few lines to set up a call to the following extension method:
> System.Reactive.Linq.Observable.Repeat<T>(this IObservable<T> source)




## Results

The AOT step fails because the "QueryLanguage" class is missing:


### Excerpts from the diagnostic build output

>   AOT Compilation exited with code 134, command:

>   Mono Ahead of Time compiler - compiling assembly /private/tmp/UnifiedSingleViewIphone1/UnifiedSingleViewIphone1/obj/iPhone/Release/mtouch-cache/64/Build/System.Reactive.Linq.dll
>   Error setting up QueryLanguage class vtable
 		
> MTOUCH: error MT3001: Could not AOT the assembly '/private/tmp/UnifiedSingleViewIphone1/UnifiedSingleViewIphone1/obj/iPhone/Release/mtouch-cache/64/Build/System.Reactive.Linq.dll'




## Workaround

Tell the linker to preserve the "System.Reactive.Linq.QueryLanguage" type. For example, use the included `linker.xml` file that preserves that type by adding the following under "Project options -> iOS Build -> Additional mtouch arguments" :

--xml=${ProjectDir}/linker.xml




## Version information (brief)

Xamarin.iOS 8.10.1.59 (13d1cdc)
Mono 4.0.1 (detached/11b5830)

Xcode 6.3.1 (7703), Build 6D1002
Comment 1 Brendan Zagaeski (Xamarin Support) 2015-05-26 23:47:27 UTC
Created attachment 11351 [details]
Diagnostic build output and version info
Comment 3 Brendan Zagaeski (Xamarin Support) 2015-05-27 00:30:28 UTC
## More precise workaround

In case it might be helpful in diagnosing the underlying issue, I just found that you only need to preserve the "Repeat" methods within the "QueryLanguage" class.

<linker>
  <assembly fullname="System.Reactive.Linq">
    <type fullname="System.Reactive.Linq.QueryLanguage">
      <method name="Repeat" />
    </type>
  </assembly>
</linker>




## Additional observation

The "QueryLanguage" class _does exist_ in the "bad" linked version of "System.Reactive.Linq.dll" that is produced by the test case (when you haven't added the `linker.xml` workaround). But the class only contains the `.ctor` method.




## "True" regression status: NOT a recent regression

If you attempt to _run_ the attached test case on 8.10.0.267 (6481535) or 8.9.1.3 (f7736a4), then rather than hitting an AOT error at _build time_, you will instead hit an AOT error at _run time_:

> Attempting to JIT compile method 'System.Reactive.Linq.Observable:.cctor ()'
> while running with --aot-only


You can use exactly the same "more precise workaround" to stop this run time AOT error.
Comment 5 Sebastien Pouliot 2015-05-27 10:16:03 UTC
The issue is that the project configuration (Release/iPhone) is using "Link all assemblies", not the default "Link SDK", setting.

That settings means the developer is responsible to ensure all non-SDK assemblies are safe to be linked. E.g. the static analyzer cannot predict reflection usage in assemblies.

Since Xamarin do not ship System.Reactive.Linq.dll (this is not SDK code) then your workaround is correct and required for "Link all assemblies". Using "Link SDK" (default) works correctly.
Comment 9 Mohit Kheterpal 2015-06-24 09:48:45 UTC
I am able to reproduce this issue with the help of test case provided in comment 0 and observed that this issue is fixed in C5SR2 build i.e. X.iOS 8.10.2.37.

Hence closing this issue.
Comment 10 Kent 2015-08-13 20:28:17 UTC
Finally got my app in a state where I can test this. I originally submitted this problem to Xamarin support via email and communicated with Brendan there.

My original use case is not actually fixed. I'm using latest stable (8.10.4.0) to test. If I don't include this in my linker config:

<assembly fullname="System.Reactive.Linq">
    <type fullname="System.Reactive.Linq.QueryLanguage">
        <method name="Repeat" />
    </type>
</assembly>

Then my application crashes on startup with this output in the iOS Device Log:

ug 14 09:54:29 Kents-iPad MyApp[5245] <Warning>: Unhandled managed exception:
An exception was thrown by the type initializer for System.Reactive.Linq.Observable (System.TypeInitializationException)
at MyApp.Services.Logger.LoggerService.get_Entries () [0x00000] in <filename unknown>:0
at MyApp.Services.Logger.LogFileSink..ctor (ILoggerService loggerService, System.IO.Stream outputStream, System.Func`1 getInputStream) [0x00000] in <filename unknown>:0
at MyApp.UI.iOS.AppDelegate.RegisterLogging (TinyIoC.TinyIoCContainer container) [0x00000] in <filename unknown>:0
at MyApp.UI.iOS.AppDelegate.InitializeIoc () [0x00000] in <filename unknown>:0
at MyApp.UI.iOS.AppDelegate.FinishedLaunching (UIKit.UIApplication app, Foundation.NSDictionary options) [0x00000] in <filename unknown>:0
at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, IntPtr principal, IntPtr delegate) [0x00000] in <filename unknown>:0
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00000] in <filename unknown>:0
at MyApp.UI.iOS.Application.Main (System.String[] args) [0x00000] in <filename unknown>:0
--- inner exception ---
Attempting to JIT compile method 'System.Reactive.Linq.Observable:.cctor ()' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.
(System.ExecutionEngineException)
(null)

Can this ticket be re-opened please?
Comment 11 Brendan Zagaeski (Xamarin Support) 2015-08-13 23:47:17 UTC
@Kent, that is the correct intended behavior. 

As mentioned in comment 0:

> the "System.Reactive.Linq" assembly has _not_ been audited by its
> authors for compatibility with the Xamarin.iOS linker

Correspondingly, the fact that an "Attempting to JIT compile method" error appears at run time is _not_ a bug in Xamarin.iOS. The correct intended way to address the run time error is indeed either to tell the linker to skip the entire `System.Reactive.Linq` assembly, or to manually preserve specific required parts of the assembly.


(To put it another way, it would be possible to file a feature request with the authors of System.Reactive.Linq to request that they audit the assembly for compatibility with the Xamarin.iOS linker.)


(To put it one more way, the "fix" for this bug was just to stop the _AOT_ error as in comment 0, thereby restoring the old "Attempting to JIT compile method" error as described in the "NOT a recent regression" section of comment 3.)

Hope that helps clear things up.



## Side note

For customers with Business and higher licenses who are following-up on RESOLVED or VERIFIED bugs, I'd recommend contacting the Support Team via email [1] rather than following-up directly in Bugzilla. That will help ensure the issue is addresses as quickly as possible as part of the normal Support Team work queue.

[1] https://kb.xamarin.com/customer/portal/articles/1632104-how-do-i-contact-xamarin-for-support-
Comment 12 Kent 2015-08-13 23:52:58 UTC
Ah, I see Brendan - sorry, I misunderstood.

That said, I would love to know how you go from the exception given to the determination of what needs to be excluded from linking. Is there any process documented on this because I actually have the exact same problem with another DLL that I have therefore included in its entirety.