Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
6
Question by Simon Says · Jul 02, 2013 at 09:07 PM · exception

Uncaught exception doesn't kill the application

For some reason, throwing an uncaught exception doesn't abort the application, i.e. all of the following code gets executed:

 function Awake() 
 {
     throw new System.Exception("Die, fiend!");
 }
 
 function Start()     
 {
     print("Still alive");
 }

Does anybody know why? And how do I make it abort?

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image markpdolby · Jul 02, 2013 at 10:18 PM 0
Share

Does it need to be run in the editor?

avatar image Simon Says · Jul 03, 2013 at 07:49 PM 1
Share

That is a strange question. Theoretically -- no, practically -- yes. Before it's released, I will test my application in the editor many times, well, because it's convenient. Anyway, the exception doesn't kill even a regular build. Just skips the rest of the method. So it's a more expensive alias for return I guess.

5 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by Simon Says · Jul 10, 2013 at 10:11 PM

So, I've found no command line switches or API to change the described behaviour. Thus I must assume there's no way to do so (also confirmed by the @Bunny83's answer). I was able to "abort" only by calling Debug.Break() for the editor, and Application.Quit() for regular builds, which exits an application normally. It left me with two options:

  1. To write my own throwing routine that would log an issue and quit.

  2. To listen to the log events and quit when an exception has been detected. As @RoflHarris and official documentation proposed.

Unfortunately, I know of no way to force my routine on other 3rd party scripts I may be using, so the option #2 looks like the only sound solution, albeit much farther down the line than I'd have liked. I ended up with this LogCallback (eventually registered in OnEnable() and unregistered in OnDisable()):

 static private void OnLogException(string _message, string _stackTrace, LogType _logType)
 {
     if (_logType == LogType.Exception) {
         if (Application.isEditor) {
             // Only break in editor to allow examination of the current scene state.
             Debug.Break();
         }
         else {
             // There's no standard way to return an error code to the OS,
             // so just quit regularly.
             Application.Quit();
         }         
     }
 } 

Thank you all for your input. It is much appreciated.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Simon Says · Jul 10, 2013 at 10:35 PM 1
Share

I wanted to mark several answers as correct, as I have seen elsewhere on this site, but couldn't figure out how. So kudos go to the people mentioned in my answer (@Bunny83 and @RoflHarris), as they came closest to answering my question(s).

avatar image
11

Answer by Bunny83 · Jul 10, 2013 at 01:00 AM

The reason is quite simple: A Unity application is not a CLI application, it is still a native code application which runs your scripts in a managed CLI environment. All callbacks that Unity provides are invoked in native C++ code. So the managed call stack starts at the entry point of the callback. An uncaught exception will go down the stack until it reaches the end. At this point Unity just displays that an exception has been caught in a callback.

An exception is by no means required to "terminate" an application. In the case of Unity an exception inside a callback just tells Unity one of the user scripts seems to be faulty. That's not a reason to terminate the whole process. Only exceptions which results in an unpredictable state should terminate the application. Since your scripts are just a "guest" inside a Unity application managed exceptions can never terminate an application.

Keep in mind that native code exceptions (which usually also throw a managed exception) can terminate the application, however that only depends on if the exception is handled by Unity or not. At the very bottom layer you have "hard-wired" exceptions which are caught by the processor itelf and handled by the opperating system. If an exception made it's way down there the OS usually only has the option to terminate a process since it can't judge what this fault means to the program. Killing a program doesn't put the OS in an undefined state, only the program itself, that's why the OS keeps on running when a process dies.

In (nowadays) rare situations when the OS can't handle the excetion, it might even stop the OS (which means you get a BSOD on windows).

Anyways, pure managed code or managed exceptions in Unity can't terminate the application, just the current managed callstack.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Simon Says · Jul 10, 2013 at 09:09 PM 2
Share

First of all, thank you for the profound answer. Still, the analogy drawn to an OS seems strange and unfitting to me. I understand that user scripts are run in a "virtual machine" inside Unity and that any uncaught exception thrown from a script is eventually caught by Unity internally. It is how this exception is handled -- printed to a log and swallowed -- that bothers me. I think abortion or pausing the execution to allow attaching a debugger would be a much more suitable reaction.

The fact that my script encountered a fatal error (i.e. unchecked exception) and keeps running puts my application in an unpredictable state. Unity's sole purpose is to run a user's application. It doesn't manage several processes publicly, nor does it allow to start several processes in parallel, as far as I know. Hence if my application (script) is in an unpredictable state, the Unity is in an unpredictable state. An OS cannot fail under an uncaught exception from user applications, because it would compromise other, independent processes. Unity, on the other hand, compromises my application by letting it run when it clearly indicated that it hit an error it cannot cope with. An OS in its place would usually at least shut down the faulty process.

Anyway, point taken and there's nothing to it but adapt. I still don't see a good reason behind this though. Just an easier implementation for Unity developers and harder debugging for script writers.

avatar image Bunny83 · Jul 11, 2013 at 12:09 AM 0
Share

You got the wrong view on the concept i guess. A Unity application is like an OS ;) The application runs on it's own. It is responsible for managing gameobjects and components. Your scripts are "just" behaviour scripts and from Unity's point of view each callback function it calls is like a "process". If the "process" (the function) throws an exception it can't be resumed and gets ter$$anonymous$$ated. Other components or callbacks are not affected by the exception in one of the functions.

$$anonymous$$eep in $$anonymous$$d that components should work on their own.

avatar image Simon Says · Jul 11, 2013 at 07:35 AM 0
Share

I understand what you're saying. It just doesn't make sense to me why would anyone want to model each callback of each $$anonymous$$onoBehaviour as a separate process, except for laziness. That's why I asked the question in the first place. GameObjects and components are interdependent -- they reference each other ins$$anonymous$$d of communicating through messages; that's a fact. It's reasonable to assume that in the real world scenarios a person would need several such objects to create a useful application and they will cooperate at some point. They are tied stronger than usual system processes. Now, even each callback of the same behaviour (which are invoked in sequence according to Unity's rules, not user's) is a virtually separate process? How good can it be? It's like assu$$anonymous$$g that Start() (i.e. more or less constructor) will have nothing to do with Update(). But it will, both callbacks will most likely access the same data. I'm trying to see a design decision behind it, yet I'm sorry, I don't see one.

avatar image
3

Answer by tnetennba · Jul 08, 2013 at 03:00 PM

Doing something like this will allow you to catch all the logging from unity and act on what type of message has been passed through to it. This way you can get when the exception is thrown and call application.quit after logging the stack trace etc.

however I would suggest that if you have code that is likely to throw and exception use try catch blocks.

 using System;
 using UnityEngine;
 
 public class CatchException : MonoBehaviour {
     
     void OnEnable()
     {
         Application.RegisterLogCallback(HandleLogEntry);
     }
 
     void Update()
     {
         throw new System.Exception();
     }
 
     void HandleLogEntry(string logEntry, string stackTrace, LogType logType)
     {
         switch (logType)
         {
                 case LogType.Exception:
                 Console.WriteLine("caught an exception being thrown");
                 break;
         }
     }
 
     void OnDisable()
     {
         Application.RegisterLogCallback(null);
     }
 }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image youblistermypaint · May 15, 2016 at 07:19 PM 0
Share

Note that Application.RegisterLogCallback is now deprecated. Use Application.log$$anonymous$$essageReceived ins$$anonymous$$d, see http://docs.unity3d.com/ScriptReference/Application-log$$anonymous$$essageReceived.html.

avatar image
0

Answer by xKroniK13x · Jul 02, 2013 at 10:24 PM

To make it abort, use Application.Quit();. However, if you look here, it says "Quits the player application. Quit is ignored in the editor or the web player." So in editor it won't quit still, but once you publish it, it will.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Simon Says · Jul 03, 2013 at 07:40 PM 0
Share

Err, no, this doesn't answer my question. Thanks for the effort though. 1) Application.Quit() will never execute after an exception. It's either or. 2) Quit is not the same as abort. Abort usually returns an error code to the OS, quit returns O$$anonymous$$. I've tried under Windows.

I suppose I could implement my own ThrowException() routine, but it's equivalent to not using exceptions at all. Why are they supported, but crippled in such a way? I couldn't find it anywhere in the documentation. And this behaviour is at least non-standard.

By the way, for the editor a man could use:

if UNITY_EDITOR

    if (Application.isEditor) {
         EditorApplication.isPlaying = false;
     }

endif

If he wanted to.

avatar image Simon Says · Jul 08, 2013 at 01:20 PM 0
Share

Funny thing -- the snippet works even without placing the file where it's contained in an "Editor" folder.

avatar image JohnnySunshine · Jul 08, 2013 at 02:59 PM 0
Share

I haven't tried this, but System.Environment.Exit might do what you need. (I guess it would also ter$$anonymous$$ate the editor though.)

avatar image Simon Says · Jul 09, 2013 at 07:47 PM 0
Share

Nope, it doesn't work. Neither does System.Environment.ExitCode property. Thanks for the tip though.

When I tried this, I found out that the error code would do me no good anyway. Because when a Unity app is launched, it returns right away and runs the actual application in parallel. I figure that the only way to indicate that something went fishy to the outside world is to write it somewhere to a file or similar.

avatar image Jamora · Jul 10, 2013 at 12:25 AM 0
Share

Why doesn't printing out your exceptions to the Editor console work for you? I seem to remember that all UnityExceptions are printed out to the console by default.

Show more comments
avatar image
0

Answer by Loius · Jul 09, 2013 at 09:06 PM

Unity keeps a log file in %localappdata%/unity something (for editor and runtime both). Why would you want your application to silently terminate, anyway? Whenever that's happened to me I've only experienced irritation, never satisfaction.

There's also Error Pause in the Console window that pauses the application when an unhandled exception is printed to the console.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Simon Says · Jul 10, 2013 at 09:42 PM 0
Share

Ideally, I would want it to display a polite apology with an explanation that an unexpected error happened and suggest that the publisher should be contacted at the earliest convenience, at which point a debugger could be attached for development builds. For the lack of other options, ter$$anonymous$$ating after printing an error into the log is still better than, well, nothing.

In development builds, logs don't get checked too often unless a visible issue appears, which could be much, much later after the original problem occurred.

In release builds, an erroneous behaviour of my application could actually lead people to believe it was designed that way. Crashing ins$$anonymous$$d would be unpleasant, but it would clearly speak of an unexpected issue and would lead to a faster reporting and fixing it.

Imagine a situation when a script throws a NullPointerException in every Update() call. To a user it would look like my app is stuttering and generally slow in performance. His likely reaction would be to uninstall it and never mention it again. If it had crashed ins$$anonymous$$d, he would be more inclined to report it, if not too early in the game. It would be also more noticeable.

avatar image Loius · Jul 11, 2013 at 07:32 AM 0
Share

Ah, gotcha. I was stuck on thinking you were trying to prevent the game from surviving errors. Glad you got it working. And thanks, by the way. I'm sure I'll eventually come across the same need and now I've got at least a starting point. :)

avatar image Simon Says · Jul 11, 2013 at 08:12 AM 0
Share

You're welcome :o)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

23 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Best Practices for exception handling Resource.Load 1 Answer

"Array out of range" when cycling weapons. 1 Answer

Using List.Count on Unity iPhone 2 Answers

What could be causing this problem reading from a Rect into a Vector2? 3 Answers

UnityEditor.TextEditor.DrawCursor - MIssing Method Exception -2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges