How are you doing global exception handling in Flex/Flash/AS3?

On the project I’m currently working I was recently assigned the following bug:

runtime errors hose application
It seems that when a RTE encountered, the app is pretty much hosed (somewhat unpredictably) until the app is reloaded.

Since non debug players simply swallow the error without any other action, I assume users of the nondebug player who encounter RTEs will report odd behavior with is more of an effect that a cause.

Is there anything we can do to handle this any better?

This is a well known issue with Flash Player. There’s no global exception handling. It’s the most voted on issue in the Flash Player bug database (https://bugs.adobe.com/jira/browse/FP-444). It’s duplicated within the Adobe bug database a few times, and even one of the duplicates is the second most voted on bug in the AS Compiler bug database (https://bugs.adobe.com/jira/browse/ASC-3139). Combine those votes and you’ve got by far the single most wanted feature in Flash Player.

My initial response to this issue was to just say it’s impossible given the current state of Flash Player. But then I got thinking about possible solutions.

What about using JavaScript?
So let’s say I’m resigned to the fact that I cannot have any kind of global exception handling. What if I set up a simple pingback function in my Flash application that was called with JavaScript through ExternalInterface? The only purpose of this function would be to notify the HTML wrapper that the application is responding. Basically the HTML pages says “Yo Flash, you alive?” and Flash says “Yup, still pinging!”

Then if you ever don’t get a ping back you know that something is seriously wrong. Like, application-is-totally-hosed type of seriously wrong. You could then at least display a big ugly crash screen overlay on top of your app and give the user a little description field to file a bug report to tell you what they were doing when the app broke. You wouldn’t be able to save the app from breaking, but you would at least tell the user that the app is broken (which is much better than letting them keep trying to use a broken application) and you might get valuable bug reports to help you find the issue.

So here’s my big question:

In your experience with Flash applications and runtime errors that cause the application to stop functioning correctly, would a simple pingback function of the main application:

  • A. continue to run after the RTE (since the pingback function is so simple, doesn’t do any Flash rendering, or for whatever other reason)
  • B. always stop running after a RTE
  • C. sometimes keep running and sometimes stop running depending on the type of RTE

I have a feeling that the answer is C, which is half useless (although might be better than nothing). But if you know for a fact that you can write some kind of function that will always stop running after ANY runtime error in your application, please let me know (maybe this could include checking something in one of the Flex manager classes? verifying your main application is still laying itself out to the right dimensions? still able to add and remove a simple item from the stage?).

Yes, I am crowdsourcing my bugs.


22 thoughts on “How are you doing global exception handling in Flex/Flash/AS3?

  1. I’d go with either A or C, and very, very rarely B. All the unhandled RTE that happened in the wild seemed to cause some part of our larger apps to stop working in new and interesting ways, but they would respond somehow to the user (not in any really helpful way),

    I myself am one of the voters on this bug, I like your thinking but from my experience depending on what part of the app caused the RTE that was usually the bit that got hosed, with some functionality still remaining.

  2. A. says:

    What about creating another swf that will act as the bridge between the app and the html (LocalConnection+ExternalInterface) – html pings the bridge, bridge pings app and back, big chance that it can still run eventhough the “main” app crashed.

  3. TJ Downes says:

    I do agree that there needs to be some sort of error handling done at the global level. I think this needs to be done similar to the way the player handles browser history, an external app that the main app communicates with and can report errors, preferably by calling a script that can email or log the error.

    One big success we have had with server-side applications is automatically emailing errors to us as they occur so we can fix the issues quickly. It also ensures that after a few weeks in production our apps are relatively bug free. It would be nice to apply a similar mechanic to Flash applications.

  4. This is a huge problem for us too, and the answer is definitely C. I’m also curious if the pingback trick could give you a false positive… like maybe if the user is in a print dialog for a while? Or will the ExternalInterface call always hang until Flash becomes responsive again?

  5. I think I’d actually prefer D) Stop running only if the Flash Player is totally hosed (which is a variant on C), in which case allowing the Player to run through the crash would not be possible anyways. And output the error result to the trace log.

    Otherwise let the application itself decide how it wants to handle and recover from the exception, if the logic is present to intercept and respond to it. Make global exception handling possible from a Flash Player event class. When a global exception occurs, dispatch a flavour of Error event which can be listened for and handled.

    Even if a security protocol is breached, allow the exception to be handled by the application and take whatever measures are necessary to maintain security. Freezing the Flash Player due to a security violation is not a preventative, it’s a hacked up bandaid that makes the technology look bad.

  6. The only solution I know of is to listen for every possible error and security event whenever I make a data call, which is not always possible when using higher-level components, and for the rest, use teh debugger and profiler to catch the bugger, and then implement a try..catch. And that still leaves all the blue sky errors that only seem to occur when you’re demoing the application at The Big Meeting to The Head Cheeze.

  7. Maybe I’m stating the obvious to point out that without the debug player the player fails silently. I think you should be able to set a flag to make even the debug player to behave this way.

    Another way besides writing listeners for every conceivable error is to contain everything in try blocks–right?

  8. > Another way besides writing listeners for every conceivable error is to contain everything in try blocks–right?

    @Phillip Kerman: Yes – but that’s hardly a sustainable solution, and doesn’t work in all scenarios. If the Flash Player can fail with the ability to provide fault error information, then it can just as well enable the the application to decide how to proceed from that fault, rather than freezing the Flash Player and rendering the application unusable from the standpoint of the user.

  9. My vote is on C, because I guess it will depend entirely on what the RTE is if it will block the entire app or just a part of it. But the proposed solution with a JavaScript pingback wouldn’t work for AIR apps, and isn’t the same issue present there also, or?

    Just a thought, would the Log API in the Flex framework be able to help in this matter? http://livedocs.adobe.com/flex/3/html/help.html?content=logging_09.html
    I haven’t used these classes myself so I don’t know if using them would enable catching all RTE’s, or any for that matter, just figured I’d throw it out there in case it’s one of those “the solution is so obvious, nobody has ever thought of it before” things… 🙂

  10. Pingback: localToGlobal » Blog Archive » news review -> 7th week of 2009

  11. IDK. You could test it like this:

    At startup create a callback function that javascript can call.
    Set a timeout in javascript that calls that flash callback function on a set interval (like once a second)
    Throw an error on purpose
    Check if js messages are still getting through
    i think the flash player team might best be able to answer your question

    you could also extend the error class or monkey patch it to make a call to javascript when an exception is thrown. don’t know if it’s possible to work with the error class. i also heard that there is a way to get the stack trace when encountering an error. just throwing ideas out there.

  12. Greg says:

    We created our own version of the mx:application class and also created our own layoutmanager class that either extends or copies the code from the mx classes. then in one function (callbacklater) in the layout manager we added a try catch block around that call because 90% of all errors that happen because of things in the flex framework can be caught here, especially the ones you cant trap with a try catch cause they are async. All the other errors we use our own try catch blocks in code. But it was the errors in the flex framework that were causing us the biggest headaches. Now we catch virtually all errors with 1 try catch statement.

    It is not an easy thing to implement and might not be possible for some. But it would be an easy fix for the flex team to implement in the framework with little overhead. sure it does not catch every error, but gets the ones you cant try/catch yourself

  13. Christophe says:

    Greg, how much work was this ? I’m thinking of compiling my own version of the Flex framework with a few try/catch statements added at strategic places (in particular to catch the DataGrid problems) but I’m not sure where to start. Can you share a bit more details ?

  14. Taylor says:

    Wow, I’m curious about Greg’s solution too. I am now one of the voters on the bug, and it burns me up that it still has a priority of “C” in their bug database.
    We are porting our app from C# over to AIR. Since it’s so easy to do, our C# app has crash reporting. It’s got a few thousand desktop installations, and even though it’s pretty solid, I still get a crash report every day or so. And sometimes of course, we’ll release a beta that will “flood” me with useful crash reports and let me get it fixed ASAP. The idea of releasing commercial software without the ability to do this scares me. I can imagine the tech support emails I’ll be getting:
    Me: “What happened?”
    Them: “Well, the app started getting weird, and then silently froze.”

    This evening I was hoping that the trace or error text was logged to stderr or stdout in hopes that I might be able to capture that and filter it. In my first tests for AIR, none of the text even goes to the std pipes, and even if it did, they don’t provide easy access to the std pipes. I was hoping that maybe Alchemy’s support(?) for pipes might help, but like I say, the text needs to go there first, and it looks like the release builds of your AIR app are pretty silent.

    I also tried enumerating through flash.desktop.NativeApplication.nativeApplication.openedWindows when the main window got deactivated, in hopes that the error dialog would be one of them and that I could react appropriately. No dice.

    For our beta testers (who are obviously more hardcore), I plan on using this cookbook trick to get it to pop up the error dialog: http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&postid=13206&loc=en_US&productid=4
    Then, at the least, they’ll be able to email me with a stack track.
    In fact, I might just leave this on for the app as a whole, considering I’d rather my users see _something_ than nothing at all.

  15. Similar problem in the java world, check for null pointers, use try/catch in your code. But it doesn’t necessarily relate to Flash. The javascript approach is interesting but I would assume it would be rather flaky. If you have a FABridge or ExternalInterface call fail it wrecks havoc on all calls following that. Great question, but I am not sure if I am a fan of ‘polling’ to be part of the error handling process. But that is just an opinion.

  16. Pingback: Global Exception Handling / Crash Reporting in Adobe AIR – Partially Solved?

Comments are closed.