April 13th, 2022

A survey of how implementations of Windows Runtime events deal with errors

There are three commonly-seen implementations of Windows Runtime events (one of which with four variants), and they deal with errors differently.

Class Disconnect
errors
Behavior for other errors
RPC_E_DISCONNECTED RPC_S_SERVER_UNAVAILABLE RPC_E_SERVER_DIED RPC_E_SERVER_DIED_DNE JSCRIPT_E_CANTEXECUTE
WRL::EventSource<
FireAll>
    Ignore errors.
WRL::EventSource<
StopOnFirstError>
    Stop on first handler to return an error and return that error.
WRL::EventSource<
ReportUnhandled-
OnFirstError-
WithWin8Quirk>
For Win8 apps: Ignore errors.
Otherwise: Stop on first handler to return an error. Raise the CoreApplication.Unhandled­Error­Detected event. If handled, then return S_OK, else return the original error.
WRL::EventSource<
StopOnFirstError-
WithWin8Quirk>
For Win8 apps: Ignore errors.
Otherwise: Stop on first handler to return an error and return that error.
C++/CX event     Stop on first handler to return an error and return that error.
winrt::event     Ignore errors.

The code for WRL::Event­Source is in wrl/event.h. The code for C++/CX event is in vccorlib.h, where it is called Platform::Event­Source. And the code for C++/WinRT winrt::event is in winrt/base.h. I built the above table by reading the code. (You can do it too.)

For WRL, the default for Event­Source is Fire­All for third-party code, and Report­Unhandled­On­First­Error­With­Win8­Quirk for Windows operating system code.

In all cases, a handler that returns one of the recognized Disconnect error codes is removed as an event handler and therefore will not receive any future events. (However, it will not be considered an error to decide whether or not to stop calling further handlers.) To avoid accidentally propagating one of these secret error codes out of your event handler, wrap your event handler in a trycatch (...) or mark your event handlers as noexcept.

In fact, given that different event sources deal with errors differently, you probably should simply avoid returning errors from your event handler. Wrap the event handler in a trycatch (...) so you can decide what to do in case of an error, or mark the event handler as noexcept to say that all errors are fatal to the application.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

2 comments

Discussion is closed. Login to edit/delete existing comments.

  • 紅樓鍮

    By the way, a lot of surnames are being truncated to one character on this blog recently. Is that one of those UTF-16-LE-interpreted-as-UTF-8 errors?

  • 紅樓鍮

    So can I implement a one-shot handler by deterministically returning RPC_E_DISCONNECTED after having done the work?