ExecutionEngineException when raising the PropertyChanged event

If you’ve ever seen an ExecutionEngineException in .NET, you know that it’s nasty. It even sounds intimidating. It’s the error that’s thrown by Environment.FailFast() — MSDN describes it as "the exception that is thrown when there is an internal error in the execution engine of the common language runtime." Before last night, the only time I’d ever seen it was when I was generating and running my own IL assembly code and I did something wrong like pop too many values off the stack or something.

However, last night I got it while raising a PropertyChanged event on my INotifyPropertyChanged object, immediately after using PropertyChangedEventManager to subscribe to it. I scratched my head…how the hell did I manage to cause an internal error in the CLR? I restarted Visual Studio, I rebooted my machine, I tried it on other machines to see if it was some sort of crazy corruption on my system, but it was completely repeatable.

Finally, in desperation, I set up .NET source stepping (something I’ve been meaning to do for a while anyway) and ran it again — this time, instead of showing up on the line where I raised the PropertyChanged event, the exception stopped on this code in WeakEventManager.cs:

            bool condition = listener.ReceiveWeakEvent(managerType, sender, args);
            if (!condition)
            {
                Invariant.Assert(condition, SR.Get("ListenerDidNotHandleEvent"), SR.Get("ListenerDidNotHandleEventDetail", new object[] { listener.GetType(), managerType }));
            }

That’s right…when ReceiveWeakEvent returns false (indicating that the listener did not handle the event being raised), WeakEventManager calls Environment.FailFast(). This is the software equivalent of people in horror movies choosing to shoot themselves in the face rather than turn into a zombie and possibly hurt their friends. It writes an event to the Event Viewer that says "Unrecoverable system error."

This may be the most ridiculously over-reactive error processing I’ve ever seen in my life, and for some reason, Google is completely unhelpful on this subject. Searching for "PropertyChangedEventManager ExecutionEngineException" turns up virtually nothing — the only result in English was a 404, and Google’s cached version didn’t have either keyword in it, for some reason. Hopefully this will save someone the intense frustration I experienced when I accidentally returned false from a random event handler somewhere, and was told that my execution engine had become unrecoverably corrupt and would be shut down for its own protection. If this post helps you, please tell me so in the comments so I’ll know my time wasn’t completely wasted.

About these ads
This entry was posted in Computers and Internet. Bookmark the permalink.

8 Responses to ExecutionEngineException when raising the PropertyChanged event

  1. Guy says:

    Dude!You sure saved my time. Lucky for me your post popped up in my second google attempt ;)enjoy–Guy

  2. Andrew says:

    Mate! Thanks! Definitely a lifesaver… Indeed, Google results didn’t play nice for me either until I finally found your post.

  3. emddudley says:

    I was really stuck until I found your blog post. I’ve put a question on StackOverflow to help give this issue higher visibility.

    http://stackoverflow.com/q/9727435/111327

  4. wonkim00 says:

    Found my way here via emddudley’s StackOverflow question. Good info!

  5. herm says:

    This one was really helpful.

  6. Gary Campbell says:

    Very nice job! Thank you

  7. It might be that this is a 4.0 only problem and is fixed in 4.5 because when I look at the source code you mentioned I see these comments:

    // legacy (4.0)

    // if the event isn’t handled, something is seriously wrong. This
    // means a listener registered to receive the event, but refused to
    // handle it when it was delivered. Such a listener is coded incorrectly.

    • ceiled says:

      Well…I mean, a comment “explaining” the reasoning is better than nothing, but the code is still there (4.5 doesn’t actually have a new WindowsBase.dll, so this code is the same between 4.0 and 4.5) but I still think it’s a really awful error handling policy. If it’s “incorrect” to return anything other than true, then why even have a Boolean return value in the first place? Why not just return void? It makes it look like there’s some sort of responsibility to properly report whether you’re interested in this event, which then just explodes in your face if you say no.

      The official documentation (http://msdn.microsoft.com/en-us/library/system.windows.iweakeventlistener.receiveweakevent(v=vs.110).aspx) is even less helpful:

      “Return Value
      Type: System.Boolean
      true if the listener handled the event. It is considered an error by the WeakEventManager handling in WPF to register a listener for an event that the listener does not handle. Regardless, the method should return false if it receives an event that it does not recognize or handle.”

      So, returning false is considered an error, but you should do it anyway if you receive an event you don’t recognize? Why would I ever want a code path in my application that might lead to the application force-quitting and logging an “Unrecoverable system error” event in the system log?

      This might all be forgivable if the error message actually said what the problem was. Reading the code, it seems like it ought to; the “ListenerDidNotHandleEventDetail” resource, which it passes to Invariant.Assert(), contains the string “Listener of type ‘{0}’ registered with event manager of type ‘{1}’, but then did not handle the event. The listener is coded incorrectly.” This at least gives enough information for the developer to figure out where the problem is.

      Unfortunately, Invariant.Assert passes that message to FailFast(string, string), which completely ignores it and passes a totally different message with no specific information (“Unrecoverable system error.”) to FailFast(string), with the result being that the user never actually sees the relatively helpful message that was passed to Invariant.Assert().

      So no, I would argue that this issue is exactly as big of a problem in 4.5 as it was when I first ran into it in 3.5, and that it’s still an extremely ill-conceived way to handle a completely innocuous “error” situation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s