Search Unity

Get symbol maps to work

Discussion in 'Web' started by claytoncurmi, Sep 30, 2020.

  1. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Hi all,

    I am currently working on a solution whereby I would like to get a meaningful stack trace from a release WebGL build (currently using Unity 2020.1.4). The idea is that I can then post this on a server to be evaluated later on. I created a small demo project with the following code. I tried building 2 builds; build 1.0.5 - development build, build 1.0.6 - non-development build with debug symbols enabled. Attached are 2 screenshots for when I generate a null reference exception.

    I don't want to use FullWithStacktrace (I am using FullWithoutStacktrace) as this will be used for a live environment and such builds have poor performance. So I would like to use the stacktrace from WASM.

    My questions are the following;

    a...Why isn't there a function name that includes 'GenerateNullReferenceException' (even though mangled it could be helpful). I noticed that when I generate a log error there is an entry with a function name that includes 'GenerateLogError' in it however this isn't the case for null reference exceptions.

    b...How can one make use of the debug symbols file? All entries in the 2nd screenshot are from (anonymous) methods. It gets generated and I can see it in build folder but it is never downloaded to the client (should it?). Does the symbols map file get loaded automatically?



    Null reference exception stack in build 1.0.5 (development build)
    upload_2020-9-30_15-17-47.png

    Null reference exception stack in build 1.0.6 (release build)
    upload_2020-9-30_15-16-45.png

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. using UnityEngine;
    6.  
    7. public class Demo : MonoBehaviour {
    8.     // Update is called once per frame
    9.     void Update () {
    10.         if (Input.GetKeyDown (KeyCode.N)) {
    11.             GenerateNullReferenceException ();
    12.         }
    13.  
    14.         if (Input.GetKeyDown (KeyCode.E)) {
    15.             GenerateLogError ();
    16.         }
    17.  
    18.         if (Input.GetKeyDown (KeyCode.T)) {
    19.             ThrowException ();
    20.         }
    21.     }
    22.  
    23.     private void GenerateNullReferenceException () {
    24.         string s = null;
    25.         s.Trim ();
    26.     }
    27.  
    28.     private void GenerateLogError () {
    29.         Debug.LogError ("Computer says no!");
    30.     }
    31.  
    32.     private void ThrowException () {
    33.         throw new System.Exception ("Kaboom!");
    34.     }
    35. }
     
    Last edited: Sep 30, 2020
  2. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Ok so today I made good improvements, however there are still some pending issues to be addressed.

    I made a series of builds to identify if I can get the null reference exception stacktrace from WASM in release build. The build that got me closest to my goal was the one built with the following settings;

    upload_2020-10-2_10-53-22.png
    upload_2020-10-2_10-53-16.png

    Which generates the following stack trace when I press the G (to execute the
    GenerateGameObjectNullReferenceException method shown below).

    Code (CSharp):
    1. Exception at:
    2. Error
    3.     at jsStackTrace (blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:22520)
    4.     at stackTrace (blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:22691)
    5.     at blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:9961
    6.     at <anonymous>:wasm-function[32174]:0x89430f
    7.     at <anonymous>:wasm-function[32028]:0x88fd33
    8.     at <anonymous>:wasm-function[9307]:0x432a07
    9.     at <anonymous>:wasm-function[10278]:0x47e42c
    10.     at <anonymous>:wasm-function[24191]:0x70a0d5
    11.     at <anonymous>:wasm-function[24189]:0x70a03a
    12.     at <anonymous>:wasm-function[31650]:0x881418
    13.     at <anonymous>:wasm-function[31646]:0x881144
    14.     at <anonymous>:wasm-function[14818]:0x5a196b
    15.     at <anonymous>:wasm-function[31778]:0x886504
    16.     at <anonymous>:wasm-function[32043]:0x88fe25
    17.     at <anonymous>:wasm-function[2951]:0x14b83a
    18.     at <anonymous>:wasm-function[2950]:0x14b7a3
    19.     at <anonymous>:wasm-function[7339]:0x316059
    20.     at <anonymous>:wasm-function[7327]:0x314ba3
    21.     at <anonymous>:wasm-function[9635]:0x448a31
    22.     at <anonymous>:wasm-function[9634]:0x44875a
    23.     at <anonymous>:wasm-function[8080]:0x367d4e
    24.     at <anonymous>:wasm-function[7431]:0x31f356
    25.     at <anonymous>:wasm-function[7431]:0x31f36d
    26.     at <anonymous>:wasm-function[7426]:0x31e583
    27.     at <anonymous>:wasm-function[7420]:0x31cdfa
    28.     at dynCall_v (<anonymous>:wasm-function[32306]:0x89919e)
    29.     at Object.dynCall_v (blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:469584)
    30.     at browserIterationFunc (blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:131380)
    31.     at Object.runIter (blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:134453)
    32.     at Browser_mainLoop_runner (blob:http://localhost:50247/856151ad-578d-4a1a-9d24-39e43f50d98f:2:132915)
    This stacktrace is good enough for me as it can be translated to the following using the symbols map;

    Code (CSharp):
    1. __ZN6il2cpp2vm9Exception5RaiseEP15Il2CppExceptionP10MethodInfo|il2cpp::vm::Exception::Raise(Il2CppException*, MethodInfo*)
    2. _il2cpp_raise_exception
    3. __Z25scripting_raise_exception21ScriptingExceptionPtr|scripting_raise_exception(ScriptingExceptionPtr)
    4. __ZN9Scripting24RaiseNullExceptionObjectE18ScriptingObjectPtr|Scripting::RaiseNullExceptionObject(ScriptingObjectPtr)
    5. __Z21Object_CUSTOM_GetNameP12Il2CppObject|Object_CUSTOM_GetName(Il2CppObject*)
    6. _Object_GetName_m6F0498EEECA37CD27B052F53ECDDA019129F3D7A
    7. _Object_get_name_m0C7BC870ED2F0DC5A2FB09628136CD7D1CB82CFB
    8. _Demo_GenerateGameObjectNullReferenceException_mC23228EE215A36BBFC1483C71036D4D590921B9E
    9. _Demo_Update_mA20CD8F8E6C14018B5051CFC4624F1559E45BA40
    10. __Z65RuntimeInvoker_TrueVoid_t700C6383A2A510C2CF4DD86DABD5CA9FF70ADAC5PFvvEPK10MethodInfoPvPS4_|RuntimeInvoker_TrueVoid_t700C6383A2A510C2CF4DD86DABD5CA9FF70ADAC5(void (*)(), MethodInfo const*, void*, void**)
    11. __ZN6il2cpp2vm7Runtime6InvokeEPK10MethodInfoPvPS5_PP15Il2CppException|il2cpp::vm::Runtime::Invoke(MethodInfo const*, void*, void**, Il2CppException**)
    12. _il2cpp_runtime_invoke
    13. __Z23scripting_method_invoke18ScriptingMethodPtr18ScriptingObjectPtrR18ScriptingArgumentsP21ScriptingExceptionPtrb|scripting_method_invoke(ScriptingMethodPtr, ScriptingObjectPtr, ScriptingArguments&, ScriptingExceptionPtr*, bool)
    14. __ZN19ScriptingInvocation6InvokeEP21ScriptingExceptionPtrb|ScriptingInvocation::Invoke(ScriptingExceptionPtr*, bool)
    15. __ZN13MonoBehaviour16CallUpdateMethodEi|MonoBehaviour::CallUpdateMethod(int)
    16. __ZN13MonoBehaviour6UpdateEv|MonoBehaviour::Update()
    17. __ZN20BaseBehaviourManager12CommonUpdateI16BehaviourManagerEEvv|void BaseBehaviourManager::CommonUpdate()
    18. __ZN13UpdateManager6UpdateEv|UpdateManager::Update()
    19. __ZZ23InitPlayerLoopCallbacksvEN41UpdateScriptRunBehaviourUpdateRegistrator7ForwardEv|InitPlayerLoopCallbacks()::UpdateScriptRunBehaviourUpdateRegistrator::Forward()
    20. __Z17ExecutePlayerLoopP22NativePlayerLoopSystem|ExecutePlayerLoop(NativePlayerLoopSystem*)
    21. __Z17ExecutePlayerLoopP22NativePlayerLoopSystem|ExecutePlayerLoop(NativePlayerLoopSystem*)
    22. __Z10PlayerLoopv|PlayerLoop()
    23. __ZL8MainLoopv|MainLoop()
    24. dynCall_v
    However when I try to execute the method
    GenerateStringNullReferenceException or
    GeneratePlayerNullReferenceException no exception is raised and it proceeds as if they were properly initialized. At this point I expect that both will fail on line 58 and line 75 respectively. Why does it crash in GenerateGameObjectNullReferenceException but not the others?

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. using UnityEngine;
    6.  
    7. public class Player {
    8.     private int health;
    9.  
    10.     public int Health {
    11.         get {
    12.             return health;
    13.         }
    14.     }
    15.  
    16.     public bool IsDead {
    17.         get {
    18.             return health == 0;
    19.         }
    20.     }
    21.     public void ApplyDamage (int damage) {
    22.         health = Mathf.Max (0, health - damage);
    23.     }
    24.  
    25. }
    26.  
    27. public class Demo : MonoBehaviour {
    28.     // Update is called once per frame
    29.     void Update () {
    30.         if (Input.GetKeyDown (KeyCode.S)) {
    31.             GenerateStringNullReferenceException ();
    32.         }
    33.  
    34.         if (Input.GetKeyDown (KeyCode.H)) {
    35.             HandleStringNullReferenceException ();
    36.         }
    37.  
    38.         if (Input.GetKeyDown (KeyCode.P)) {
    39.             GeneratePlayerNullReferenceException ();
    40.         }
    41.  
    42.         if (Input.GetKeyDown (KeyCode.G)) {
    43.             GenerateGameObjectNullReferenceException ();
    44.         }
    45.  
    46.         if (Input.GetKeyDown (KeyCode.E)) {
    47.             GenerateLogError ();
    48.         }
    49.  
    50.         if (Input.GetKeyDown (KeyCode.T)) {
    51.             ThrowException ();
    52.         }
    53.     }
    54.  
    55.     private void GenerateStringNullReferenceException () {
    56.         Debug.Log ("Generating null reference exception");
    57.         string s = null;
    58.         s.Trim ();
    59.         Debug.Log (s.Length);
    60.     }
    61.  
    62.     private void HandleStringNullReferenceException () {
    63.         Debug.Log ("Handling null reference exception");
    64.         try {
    65.             string s = null;
    66.             s.Trim ();
    67.             Debug.Log (s.Length);
    68.         } catch (Exception ex) {
    69.             Debug.LogError (ex.Message);
    70.         }
    71.     }
    72.  
    73.     private void GeneratePlayerNullReferenceException () {
    74.         Player p = null;
    75.         p.ApplyDamage (5);
    76.         Debug.Log ("Health - " + p.Health);
    77.         Debug.Log ("Is dead - " + p.IsDead);
    78.     }
    79.  
    80.     private void GenerateGameObjectNullReferenceException () {
    81.         var go = GameObject.Find ("NonExistentObject");
    82.         Debug.Log (go.name);
    83.     }
    84.  
    85.     private void GenerateLogError () {
    86.         Debug.LogError ("Computer says no!");
    87.     }
    88.  
    89.     private void ThrowException () {
    90.         throw new System.Exception ("Kaboom!");
    91.     }
    92. }
     
    Last edited: Oct 5, 2020
  3. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Another update regarding the code below. Why does the method GenerateStringNullReferenceExceptionOriginal does not generate a null reference exception but GenerateStringNullReferenceExceptionContains does?

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. using UnityEngine;
    7.  
    8. public class Player {
    9.     private int health;
    10.  
    11.     public int Health {
    12.         get {
    13.             return health;
    14.         }
    15.     }
    16.  
    17.     public bool IsDead {
    18.         get {
    19.             return health == 0;
    20.         }
    21.     }
    22.     public void ApplyDamage (int damage) {
    23.         health = Mathf.Max (0, health - damage);
    24.     }
    25.  
    26.     public void PrintName () {
    27.         Debug.Log ("Player One");
    28.     }
    29.  
    30. }
    31.  
    32. public class Demo : MonoBehaviour {
    33.     // Update is called once per frame
    34.     void Update () {
    35.         if (Input.GetKeyDown (KeyCode.Q)) {
    36.             GenerateStringNullReferenceExceptionOriginal ();
    37.         }
    38.  
    39.         if (Input.GetKeyDown (KeyCode.W)) {
    40.             GenerateStringNullReferenceExceptionTrim ();
    41.         }
    42.  
    43.         if (Input.GetKeyDown (KeyCode.E)) {
    44.             GenerateStringNullReferenceExceptionContains ();
    45.         }
    46.  
    47.         if (Input.GetKeyDown (KeyCode.R)) {
    48.             HandleStringNullReferenceException ();
    49.         }
    50.  
    51.         if (Input.GetKeyDown (KeyCode.T)) {
    52.             GeneratePlayerNullReferenceException ();
    53.         }
    54.  
    55.         if (Input.GetKeyDown (KeyCode.Y)) {
    56.             GenerateGameObjectNullReferenceException ();
    57.         }
    58.  
    59.         if (Input.GetKeyDown (KeyCode.U)) {
    60.             GenerateLogError ();
    61.         }
    62.  
    63.         if (Input.GetKeyDown (KeyCode.I)) {
    64.             ThrowException ();
    65.         }
    66.     }
    67.  
    68.     private void GenerateStringNullReferenceExceptionOriginal () {
    69.         Debug.Log ("Generating null reference exception (original)");
    70.  
    71.         string s = null;
    72.         s.Trim ();
    73.         Debug.Log (s.Length);
    74.     }
    75.  
    76.     private void GenerateStringNullReferenceExceptionContains () {
    77.         Debug.Log ("Generating null reference exception (contains)");
    78.         string s = null;
    79.  
    80.         if (s == null) {
    81.             Debug.Log ("String is null!");
    82.  
    83.             s.Contains ("Hello");
    84.  
    85.             if (s != null) {
    86.                 Debug.Log ("String is not null!");
    87.             }
    88.  
    89.             Debug.Log (s.Length);
    90.         } else {
    91.             s.Trim ();
    92.             Debug.Log (s.Length);
    93.         }
    94.     }
    95.  
    96.     private void GenerateStringNullReferenceExceptionTrim () {
    97.         Debug.Log ("Generating null reference exception (trim)");
    98.         string s = null;
    99.  
    100.         if (s == null) {
    101.             Debug.Log ("String is null!");
    102.  
    103.             s.Trim ();
    104.  
    105.             if (s != null) {
    106.                 Debug.Log ("String is not null!");
    107.             }
    108.  
    109.             Debug.Log (s.Length);
    110.         } else {
    111.             s.Trim ();
    112.             Debug.Log (s.Length);
    113.         }
    114.     }
    115.  
    116.     private void HandleStringNullReferenceException () {
    117.         Debug.Log ("Handling null reference exception");
    118.         try {
    119.             string s = null;
    120.             s.Trim ();
    121.             Debug.Log (s.Length);
    122.         } catch (Exception ex) {
    123.             Debug.LogError (ex.Message);
    124.         }
    125.     }
    126.  
    127.     private void GeneratePlayerNullReferenceException () {
    128.         Player p = null;
    129.  
    130.         if (p == null) {
    131.             Debug.Log ("Player is null!");
    132.  
    133.             p.PrintName ();
    134.  
    135.             if (p != null) {
    136.                 Debug.Log ("Player is not null!");
    137.             }
    138.  
    139.             Debug.Log (p.Health);
    140.         } else {
    141.             p.ApplyDamage (5);
    142.             Debug.Log ("Health - " + p.Health);
    143.             Debug.Log ("Is dead - " + p.IsDead);
    144.         }
    145.     }
    146.  
    147.     private void GenerateGameObjectNullReferenceException () {
    148.         var go = GameObject.Find ("NonExistentObject");
    149.         Debug.Log (go.name);
    150.     }
    151.  
    152.     private void GenerateLogError () {
    153.         Debug.LogError ("Computer says no!");
    154.     }
    155.  
    156.     private void ThrowException () {
    157.         throw new System.Exception ("Kaboom!");
    158.     }
    159. }
    160.  
     
    Last edited: Oct 6, 2020
  4. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    In order to have the build retain the function callstack names, instead of showing those wasm-function[1234], you can pass the directive

    PlayerSettings.WebGL.emscriptenArgs = " --profiling-funcs ";

    to a build in an Editor script. That will include the function symbol names in the .wasm file. Do notice however that including symbols does increase the size of the .wasm file by some amount.

    You can try using the attached buildWebGL.cs build script. (check its contents for documentation)
     

    Attached Files:

    Meltdown and RMGK like this.
  5. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    Oh, forgot to mention - the option Enable Exceptions: None/Explicit/FullWithStacktrace does not relate to the presence of the function symbol names, but rather to the presence of try-catch clauses in the generated code.
     
  6. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Thanks for your reply.

    I have recovered the required function names using the debugSymbols options (set to true) as explained in post #2 - https://forum.unity.com/threads/get-symbol-maps-to-work.979944/#post-6374373. This generated a JSON file which includes the ID and associated function name. Using a simple lookup code I was able to convert wasm-function[1234] to the required function name.

    The problem I have is as explained at the end of the same post, that certain functions trigger a null exception (for example GenerateGameObjectNullReferenceException) but not others such as GenerateStringNullReferenceException when they should. In fact the same code when executed in development build will generate the null reference (which is correct). I also posted another update with my latest findings as you can see above in post #3.

    Could you indicate why this happens and how can we avoid this from happening?
     
  7. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    In a nutshell these are the results I am getting with these two builds (using the code from post #3);

    Build A
    -----------
    Enable Exceptions - FullWithoutStacktrace
    Build Type - Release
    Debug Symbols - Enabled
    Stack Trace - Full (for all log types)
    -----------
    Press 'Q' - Generates exception but no debug symbols in stack trace
    Press 'W' - Generates exception but no debug symbols in stack trace
    Press 'E' - Generates exception but no debug symbols in stack trace
    Press 'R' - Handles exception and outputs error log with debug symbols in stack trace
    Press 'T' - Generates exception but no debug symbols in stack trace
    Press 'Y' - Generates exception but no debug symbols in stack trace
    Press 'U' - Outputs error log with debug symbols in stack trace
    Press 'I' - Generates exception but no debug symbols in stack trace


    Build B
    -----------
    Enable Exceptions - None
    Build Type - Release
    Debug Symbols - Enabled
    Stack Trace - Full (for all log types)
    -----------
    Press 'Q' - No error
    Press 'W' - No error
    Press 'E' - Generates exception and has debug symbols in stack trace
    Press 'R' - No error
    Press 'T' - No error
    Press 'Y' - Generates exception and has debug symbols in stack trace
    Press 'U' - Outputs error log with debug symbols in stack trace
    Press 'I' - Generates exception and has debug symbols in stack trace

    As you can see these are totally different outputs. What I want is to have the same exceptions fired as in Build A with debug symbols in the stack trace. Is that possible?
     
  8. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    Hmm, yeah, try doing a Release build with Full with stack trace, Debug Symbols - Enabled, Stack Trace - Full, but do the build via the buildWebGL.cs script I posted.

    In the build dropdown that appears, try out the option "HTML5 Export/Wasm+Release+Profiling uncompressed...". Does that give the stack trace information?
     
  9. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    So I imported the script attached in the previous post and made two builds as follows;

    Build A
    -----------
    Enable Exceptions - FullWithoutStackTrace
    Ran the command "HTML5 Export/Wasm+Release+Profiling uncompressed..."

    This generates a stack trace that is identical to the output as in my first post. As indicated again below there is no mention of the method that triggered the exception and therefore I would be unable to track the issue down.

    upload_2020-10-6_12-12-29.png



    Build B
    -----------
    Enable Exceptions - FullWithStackTrace
    Ran the command "HTML5 Export/Wasm+Release+Profiling uncompressed..."

    This generates a partial stack trace in the message (printed in red) as shown below. But as pointed in the documentation "FullWithStackTrace exception support will decrease performance and increase browser memory usage. Only use this for debugging purposes and make sure to test in a 64-bit browser". As this is a tool meant to run in a release environment, this option is not possible.

    upload_2020-10-6_12-15-57.png


    As indicated in post #7, the best output I had so far in terms of logging is when I made a build with Enable Exceptions set to None. In this case when I press E, Y or I, a log as shown below is outputted (the one on the left is the actual log given from the WebGL player, the one on the right is how the stacktrace after using the lookup symbols map) and as you can see on line 8 it indicates the origin of the problematic code which is great. The problem is that the code doesn't always crash when it should as when pressing Q, W, R or T.

    upload_2020-10-6_12-34-0.png
     

    Attached Files:

  10. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    This seems like the method may have gotten inlined, or some other issue. This may be worth filing a bug.

    I believe this is something we have fixed just recently, in a feature that adds such safety checks even when Enable Exceptions is set to None.
     
  11. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Ok thanks for you reply,

    So when calling s.Trim() on the null string variable 's' or accessing the method of a non-initialised instance of the Player class, the WebGL player should crash, irrespective of Enable Exceptions value, right?

    Is this the bug fix you are referring to https://issuetracker.unity3d.com/is....1781848397.1601903533-1090151897.1564650624? In which version will it be available? Thanks once again.
     
  12. De-Panther

    De-Panther

    Joined:
    Dec 27, 2009
    Posts:
    589
  13. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    I am asking if that is the actual bug fix as I am not sure. If it is, it didn't solve my issue as I tried 2020.1.7f1 already and same results as before.
     
  14. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    Currently if `null.Function()` is called, the WebGL build will:
    - happily truck through the line to a random crash or no-crash if the page was built with Player->Publishing Settings->Enable Exceptions set to Explicit or None, and
    - throw an exception if the page was built with Enable Exceptions set to Full (with or without Stacktrace)

    The first mode is good for generating smallest code size and performance for the web in the Release scenario where one has already debugged through all kinds of code issues like null references. The second mode is good for debugging, but comes with quite a large penalty on WebAssembly code size and startup load times, and to a smaller degree to runtime performance.

    Recently we realized that we are missing a third kind of mode in between, where we would safely abort execution (by raising a WebAssembly trap) if `null.Function()` is met, but without the penalty on code size, load times or performance. That mode would be good for shipping final projects, while still retaining the ability to get meaningful error reports back to analytics (by e.g. JavaScript window.onerror() based error handlers)

    This mode is not listed under the issue tracker since it was observed based on our internal communication, and not due to an error report that was submitted.

    Further discussing with our codegen team today, it does look like the function did get inlined. That brings a tricky situation: I understood you would like to get these reports from Release builds. Because inlining is critical for small code size, disabling inlining to get the stack trace would cause quite a large code size penalty that might not be worth the tradeoff. Building in debug mode would limit the amount of inlining, but that would definitely run quite slow. Not sure what to suggest here..
     
  15. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Ok thanks for your detailed explanation, much appreciated.

    Unfortunately this won't allow us to track the origin of the issue and might cause unwanted and misleading side effects. Is there a different approach that we can take to get meaningful error logs from a release WebGL environment (except using the FullWithStacktrace option) with the currently available Unity versions?

    In conclusion, what we are truly really after is the 3rd mode whereby an exception is fired for null.Function() without penalty on code size or performance. Do you have an indication when this feature will be available and in which version?
     
  16. jukka_j

    jukka_j

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    953
    Inlining may be something that happens aggressively in small synthetic test cases like shown above, but in real world code, it may be less common, depending on the sizes of the functions and how many times they are called. Unfortunately I do not have a solution here. Do note that the same inlining will occur on all IL2CPP platforms, not just specifically on WebGL.
    [/QUOTE]

    Sorry, we do not have visibility to that yet.
     
  17. claytoncurmi

    claytoncurmi

    Joined:
    Jul 6, 2010
    Posts:
    168
    Ok thanks for your time.
     
  18. RMGK

    RMGK

    Joined:
    Sep 30, 2011
    Posts:
    75
    This worked like a charm! Thank you!
     
    OceanX000 and UtsavJam like this.