Unity Community


Page 1 of 2 12 LastLast
Results 1 to 20 of 27

  1. Posts
    51

    ExecutionEngineException on iOS only ??

    I'm running some custom networking code (not sure if that's related or not), but said networking code makes use of the C# Interlocked functionality. The following exception is only thrown when running the app on iOS hardware (IPad 2, 5.0)

    ... it works flawlessly on Windows and on Mac.

    Any idea why this is blowing up on iOS?

    ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native) System.Threading.Interlocked:CompareExchange (Shared.LogMessageDelegate&,Shared.LogMessageDeleg ate,Shared.LogMessageDelegate)' while running with --aot-only.
    Last edited by Alchemyst; 12-01-2011 at 10:27 PM.


  2. Posts
    51
    It looks like this is actually happening anytime I try to hook up a .net style event handler in an external C# assembly...i.e.

    Logger.Log += new LogMessageDelegate(Method);

    Is this not supported?


  3. Location
    Zürich, Switzerland
    Posts
    26,572
    As iOS does not allow dynamic code generation, all code for iOS is AOT compiled which has various restrictions especially along the line of reflection and dynamic evaluation of the real content.

    Also don't forget that iOS does not have the full .NET subset, so just cause it works on win or osx has no meaning for iOS development (not even that it works on android has that, as Android is a JIT platform, not an AOT)


  4. Posts
    51
    Quote Originally Posted by dreamora View Post
    As iOS does not allow dynamic code generation, all code for iOS is AOT compiled which has various restrictions especially along the line of reflection and dynamic evaluation of the real content.

    Also don't forget that iOS does not have the full .NET subset, so just cause it works on win or osx has no meaning for iOS development (not even that it works on android has that, as Android is a JIT platform, not an AOT)
    Got it, but I'm still having trouble understanding how hooking up an event handler (located in a standard DLL assembly) via the += syntax causes a JIT compilation. I thought JIT compilations are only a danger in certain instances concerning Generics and Generic collections.

    No? I was under the impression that events are supported on iOS.


  5. Location
    Zürich, Switzerland
    Posts
    26,572
    Events normally work and I've never seen it fail either.

    Your error though also points towards threading which you can't use with unityengine.object extending classes for example (but that would not result in an exception on assignement, it would crash upon calling)


  6. Posts
    51
    Looke like the problem is related to DLLs created in Visual Studio 2010.
    ------------
    Full-AOTing a VS2008 built .NET assembly and using an event within said
    assembly works fine. However if the assembly is built in VS2010, all other
    things being equal, it does JIT code during event subscriptions,
    Specifically within 'Interlocked.CompareExchange<EventHandler>'.

    I used reflector on two basic .NET assemblies, one built with VS2008, and
    the other with VS2010, and it turns out the default generated add-remove
    event methods have changed:

    ##### 2008 #####

    Code:  
    1. public event EventHandler SomethingHappened;
    2. [MethodImpl(MethodImplOptions.Synchronized)]
    3. public void add_SomethingHappened(EventHandler value)
    4. {
    5.     this.SomethingHappened = (EventHandler)
    6. Delegate.Combine(this.SomethingHappened, value);
    7. }
    8. [MethodImpl(MethodImplOptions.Synchronized)]
    9. public void remove_SomethingHappened(EventHandler value)
    10. {
    11.     this.SomethingHappened = (EventHandler)
    12. Delegate.Remove(this.SomethingHappened, value);
    13. }

    ##### 2010 #####

    Code:  
    1. public event EventHandler SomethingHappened
    2. {
    3.     add
    4.     {
    5.         EventHandler handler2;
    6.         EventHandler somethingHappened = this.SomethingHappened;
    7.         do
    8.         {
    9.             handler2 = somethingHappened;
    10.             EventHandler handler3 = (EventHandler)
    11. Delegate.Combine(handler2, value);
    12.             somethingHappened =
    13. Interlocked.CompareExchange<EventHandler>(ref this.SomethingHappened,
    14. handler3, handler2);
    15.         }
    16.         while (somethingHappened != handler2);
    17.     }
    18.     remove
    19.     {
    20.         EventHandler handler2;
    21.         EventHandler somethingHappened = this.SomethingHappened;
    22.         do
    23.         {
    24.             handler2 = somethingHappened;
    25.             EventHandler handler3 = (EventHandler) Delegate.Remove(handler2,
    26.             somethingHappened =
    27. Interlocked.CompareExchange<EventHandler>(ref this.SomethingHappened,
    28. handler3, handler2);
    29.         }
    30.         while (somethingHappened != handler2);
    31.     }
    32. }


  7. Posts
    51
    Further research indicates (elsewhere on the internet) that calling the offending BCL method yourself somewhere in your code sould force the AOT compiler to precompile the method. I've attempted to do so with the above referenced method:

    System.Threading.Interlocked:CompareExchange (Shared.LogMessageDelegate&,Shared.LogMessageDeleg ate,Shared.LogMessageDelegate)

    This didn't work and the iOS build still blew up when hooking up an event. I will install VS2008 and will attempt to rebuild the libraries there. I'll see if that's what it comes down to.


  8. Location
    Zürich, Switzerland
    Posts
    26,572
    You could go the save path and not compile the DLL with VS at all and use MonoDevelop instead (just use the same sln), then its as compatible as it can be.
    That it should work like this on VS 2010 vs 2008 sounds strange, unless you built it for .NET 4 where it would make sense due to the auto parallelizing compiler, because both use the same compiler normally which is part of the .net installation.
    But .NET 4 DLLs shouldn't even run in Unity, only .NET 2 DLLs (I only use VS 2010 for WP7 dev, the rest is done through VS 2008 Pro, so I can't speak from experience here)


  9. Posts
    51
    Okay. I've spent another day trying to track this down. My conclusion is that it is not possible to hook up a C# event handler on iOS if that event resides in a 3rd party C# DLL. At least not since Unity 3.0 when they upgraded to the newer Mono version (not sure about before then).

    Apparently, the .NET runtime switched from using "lock" when appending event delegates (when you use += to attach a new event handler) to using a lockless version that calls Interlocked.CompareExchange, which for some reason isn't AOT'd during the AOT compile pass and so iOS blows up on it every time you try to attach an event handler. It works just fine on Windows/Mac. Specifically, this is the error:

    Code:  
    1. ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native) System.Threading.Interlocked:CompareExchange (iOSTest.MyEventDelegate&,iOSTest.MyEventDelegate,iOSTest.MyEventDelegate)' while running with --aot-only.
    2.  
    3.   at iOSTest.EventTest.add_TestEvent (iOSTest.MyEventDelegate value) [0x00000] in <filename unknown>:0
    4.   at TestScript.Awake () [0x00000] in <filename unknown>:0

    - I have tried compiling the code on Windows with VS and on Mac with MonoDevelop
    - I've tried changing the .NET/Mono runtime from 3.5 to 3.0 to 2.0. Still no dice.

    I have created a test project that illustrates this error. Attached.

    This is quite bad, for me, because I've invested a great deal of time and money developing a client library for Unity, which relies significantly on events. It will cost a great deal more to convert it to an eventless system. I hope there is a magic compiler switch or something to that effect that would allow me to solve this problem. I'll submit a bug report, I suppose.
    Attached Files
    Last edited by Alchemyst; 12-01-2011 at 10:29 PM.


  10. Posts
    51
    I have found a (rather annoying, but doable) workaround. Essentially, you have to define your own _add / _remove handler for the delegate invocation list to prevent the compiler from generating the code that for some reason isn't included in the AOT pass.

    Code that doesn't work on iOS looked like this (from the previously attached package/zip):
    Code:  
    1. using System;
    2. namespace iOSTest
    3. {
    4.     // Event handler method signature
    5.     public delegate void MyEventDelegate(string msg);
    6.    
    7.     public class EventTest
    8.     {
    9.         // Delegate / Handler method signature
    10.         public event MyEventDelegate TestEvent;
    11.                        
    12.         public void FireEvent()
    13.         {
    14.             // Fire the event if a delegate has been hooked up.
    15.             if(TestEvent != null)
    16.             {
    17.                 TestEvent("Event fired successfully.");
    18.             }
    19.         }              
    20.     }
    21. }


    Fixed code looks like this:
    Code:  
    1. using System;
    2. namespace iOSTest
    3. {
    4.     // Event handler method signature
    5.     public delegate void MyEventDelegate(string msg);
    6.    
    7.     public class EventTest
    8.     {
    9.         // Multi-cast function pointer.
    10.         MyEventDelegate TestEventInvoker;
    11.        
    12.         // Delegate / Handler method signature
    13.         public event MyEventDelegate TestEvent
    14.         {
    15.             add
    16.             {
    17.                 TestEventInvoker += value;
    18.             }
    19.             remove
    20.             {
    21.                 TestEventInvoker -= value;
    22.             }
    23.         }
    24.            
    25.         public void FireEvent()
    26.         {
    27.             // Fire the event if a delegate has been hooked up.
    28.             if(TestEventInvoker != null)
    29.             {
    30.                 TestEventInvoker("!!!Test Message Successful.!!!");
    31.             }
    32.         }
    33.        
    34.        
    35.     }
    36. }

    Why does everything in iOS have to be SO painful? ;(
    Last edited by Alchemyst; 12-01-2011 at 10:31 PM.


  11. Location
    Zürich, Switzerland
    Posts
    26,572
    has nothing to do with iOS. Affects all AOT platform (so all consoles too for example).

    But its interesting if you are really right that 2010 is causing it, would be another reason on the list on why I am on 2008 and will stay there (it might have to do with the C# changes along .net 4 that the generated cil differs. As 2008 is up to C# 3.5 its in sync with unity, as .NET 4 / C# 4 etc is not supported at all)


  12. Posts
    51
    Yes, you're absolutely right - it's not specific to iOS - rather it's an issue with all AOT platforms. Although I'm guessing that means Android should be exempt from this bug since it's a JIT platform.

    Also, I've come to the conclusion that it has nothing to do with the IDE, but rather with the .NET runtime version that the MSIL (DLL) is being AOT compiled against - which in the case of Unity3 is the version that generates the Interlocked.CompareExchange code.

    All in all, it looks like when the AOT compiler emits code there are some instances where it doesn't AOT compile the code that it emits - at least in the case of events.

    After looking into it some more, this may be a mono bug that could have been resolved in a later version than what Unity is using.
    https://bugzilla.novell.com/show_bug.cgi?id=444218#c1

    So... in conclusion to anyone with the same problem reading this - Since there is a strong indication that this is a Mono runtime bug, I doubt this will be getting fixed any time soon (unless there is some magical way of building the package which resolves this issue).

    Use the workaround of coding your own _add/_remove methods that's posted above.
    Last edited by Alchemyst; 12-02-2011 at 10:04 AM.


  13. Location
    Zürich, Switzerland
    Posts
    26,572
    Unity does not use MS .NET at all, its mono 2.6 which is .NET 3.5 and lower + an own custom AOT compiler from Unity Technologies potentially (they wrote their own for unity iphone 1.x and have an own custom mono 2.6 version)


  14. Posts
    51
    This is quite trivial, but might help someone who's running into this... just a quick C# console script to generate the necessary event signatures (the resulting signatures are thread safe, for whatever that's worth). I've tested this on iOS, OSX and Windows.

    Just switch out "delType" and "eventName" variables and run. Resulting code is automatically copied to clip board. Just paste it into your CS file.

    Code:  
    1. using System;
    2. using System.Text;
    3. using System.Windows.Forms;
    4.  
    5. namespace EventHandlerGenerator
    6. {
    7.     class Program
    8.     {
    9.         static StringBuilder sb = new StringBuilder();
    10.         static void w(string msg)
    11.         {
    12.             System.Diagnostics.Debug.WriteLine(msg);
    13.             sb.AppendLine(msg);
    14.         }
    15.        
    16.         [STAThread]
    17.         static void Main(string[] args)
    18.         {
    19.             string delType = "EventHandlerDelegateType";
    20.             string eventName = "EventName";
    21.  
    22.              w(string.Format("#region {0} Event", eventName));
    23.              w(string.Format("private {0} {1}Invoker;", delType, eventName));
    24.             w("");
    25.             w("/// <summary>");
    26.             w("/// Your comment here");
    27.             w("/// </summary>");
    28.             w(string.Format("public event {0} {1}", delType, eventName));
    29.             w("{");
    30.             w("add");
    31.             w("{");
    32.             w(string.Format("AddHandler_{0}(value);", eventName));
    33.             w("}");
    34.             w("remove");
    35.             w("{");
    36.             w(string.Format("RemoveHandler_{0}(value);", eventName));
    37.             w("}");
    38.             w("}");
    39.             w("");
    40.             w("[MethodImpl(MethodImplOptions.Synchronized)]");
    41.             w(string.Format("private void AddHandler_{0}({1} value)", eventName, delType));
    42.             w("{");
    43.             w(string.Format("{0}Invoker = ({1})Delegate.Combine({2}Invoker, value);", eventName, delType, eventName));
    44.             w("}");
    45.             w("");
    46.             w("[MethodImpl(MethodImplOptions.Synchronized)]");
    47.             w(string.Format("private void RemoveHandler_{0}({1} value)", eventName, delType));
    48.             w("{");
    49.             w(string.Format("{0}Invoker = ({1})Delegate.Remove({2}Invoker, value);", eventName, delType, eventName));
    50.             w("}");
    51.             w("");
    52.             w(string.Format("private void Fire{0}()", eventName));
    53.             w("{");
    54.             w(string.Format("if ({0}Invoker != null)", eventName));
    55.             w("{");
    56.             w(string.Format("{0}Invoker();", eventName));
    57.             w("}");
    58.             w("}");
    59.             w("#endregion");
    60.  
    61.  
    62.             Clipboard.SetText(sb.ToString());
    63.  
    64.         }
    65.     }
    66. }
    Last edited by Alchemyst; 12-02-2011 at 01:01 PM.


  15. Posts
    2

    Having same trouble

    Hi Guys,
    I'm having the exact same issue - have a dll built from VS2010 and I get the AOT compile error when I run my game on iOS (on the IPAD2 device). I'm going to try the alternative that Alchemist suggested (with add/remove ) methods. Thanks for the solution though, I was almost beginning to think I should get rid of events from my code.
    arun


  16. Location
    Voss, Norway
    Posts
    87
    Just want to say thank you to @Alchemyst. You've just saved me hours upon hours of painful AOT debugging!


  17. Posts
    14

    How to use your workaround on +=

    Hi

    Are experiencing the same problem trying to use the XMPP framework to work with iOS using Unity/Monotouch/C#.

    This is the error I get:

    Code:  
    1. ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native)
    2. System.Threading.Interlocked:CompareExchange  
    3. (System.EventHandler`1<Matrix.EventArgs>&,System.EventHandler`1<Matrix.EventArgs>,
    4. System.Eve ntHandler`1<Matrix.EventArgs>)' while running with --aot-only.
    5.  
    6.   at Matrix.Net.BaseSocket.add_OnConnect (System.EventHandler`1 value) [0x00000]
    7. in <filename unknown>:0
    8.   at Matrix.XmppStream..ctor (StreamType type) [0x00000] in <filename unknown>:0
    9.   at Matrix.Xmpp.Client.XmppClient..ctor () [0x00000] in <filename unknown>:0
    10.   at TestFacebook.setup () [0x00000] in <filename unknown>:0
    11.   at TestFacebook.Start () [0x00000] in <filename unknown>:0
    12.  
    13. (Filename:  Line: -1)

    Most likely from this line:

    Code:  
    1. xmppClient.OnBeforeSasl += this.xmppClient_OnBeforeSasl;

    where xmppClient_OnBeforeSasl is my own custom method:

    Code:  
    1. public void xmppClient_OnBeforeSasl(object sender, Matrix.Xmpp.Sasl.SaslEventArgs e)
    2.     { ... }

    How to apply your workaround on my example? Can't see any += in your case.

    Best Regards
    Jonas Andersson

    Edit: Looking at your workaround again, it looks like you are changing the code of the library? What if it is in a dll library?
    Last edited by sunkas85; 08-21-2012 at 12:18 AM.


  18. Posts
    1
    Above there was posted that those problems don't exist when the code is compiled with VS2008. Is this true? Our code does not depend on 4.0 and could be copiled also with VS2008. Is this a solution?

    Currently we compile with default settings in Mono Develop under windows which causes the same problems. Are there any compiler settings for Monodevelop to fix this?

    Edit: The same code works on MonoTouch without any problems and changes. So what is MonoTouch doing different?

    Thanks,
    Alex
    Last edited by gnauck; 08-22-2012 at 04:10 AM.


  19. Posts
    6
    Thanks @Alchemyst, saved us a lot of trouble and guessing!


  20. Location
    Zürich, Switzerland
    Posts
    26,572
    Quote Originally Posted by gnauck View Post
    Above there was posted that those problems don't exist when the code is compiled with VS2008. Is this true? Our code does not depend on 4.0 and could be copiled also with VS2008. Is this a solution?

    Currently we compile with default settings in Mono Develop under windows which causes the same problems. Are there any compiler settings for Monodevelop to fix this?

    Edit: The same code works on MonoTouch without any problems and changes. So what is MonoTouch doing different?

    Thanks,
    Alex
    Mono touch has a different mono and aot compiler than Unity. Both use their own fork of Mono for this purpose.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •