Port crash-resistant event handler as wil::winrt_event<T, Traits>#619
Port crash-resistant event handler as wil::winrt_event<T, Traits>#619
wil::winrt_event<T, Traits>#619Conversation
Port the ResilientEvent from WidgetDeveloperPlatform as wil::winrt_event<T, Traits> in cppwinrt_authoring.h. Adds three traits classes (swallow, propagate, failfast) and the winrt_event template that wraps handlers in try/catch at registration time to support configurable exception handling. Default behavior swallows exceptions so all handlers are invoked even if some throw. Tests added to CppWinRTAuthoringTests.cpp. Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
wil::winrt_event<T, Traits>
| { | ||
| handler(std::forward<decltype(args)>(args)...); | ||
| } | ||
| catch (...) |
There was a problem hiding this comment.
@copilot update this so the traits by-default use "wil::LogCaughtException" or whatever it's called, but that can be disabled with a flag.
There was a problem hiding this comment.
Updated in 808b460. swallow_event_errors_traits::on_handler_exception now calls LOG_CAUGHT_EXCEPTION() before returning false (keeping the handler). If you want to suppress logging, implement custom traits with an empty on_handler_exception — the doc comment notes this.
|
|
||
| int value = 0; | ||
| auto token = test.MyEvent([&](const winrt::Windows::Foundation::IInspectable&, int args) { | ||
| value = args; |
There was a problem hiding this comment.
@copilot This should have a test that verifies the "caught, not leaked" behavior. Be sure to verify the "no filter" and "some filter" and "all filter" behavior from above.
There was a problem hiding this comment.
Added comprehensive tests in 808b460:
WinrtEventSwallowExceptions: verifies exception is caught, not leaked (logged viaTestFailureCache) and handlers are kept (no filter — all handlers invoked)WinrtEventRpcResilienceRemovesBrokenHandler: verifies RPC errors remove the broken handler on next invoke (some filter — RPC errors removed)WinrtEventRpcResilienceKeepsHandlerOnNonRpcError: verifies non-RPC errors keep the handler (some filter — only RPC filtered out)WinrtEventCustomTraits: verifies custom traits can implement selective removal logic (custom filter withE_ABORT→ remove, all others → swallow)
…vent_errors_traits, handler removal support, better tests Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Extended in 808b460 to include broken handler removal from the original PR concept: |
Ports
ResilientEventfrom WidgetDeveloperPlatform intocppwinrt_authoring.haswil::winrt_event<T, Traits>, where exception-handling behavior is configurable via traits. Includes support for automatic removal of broken (disconnected) handlers.New types in
wil/cppwinrt_authoring.hTraits (control what happens when a handler throws;
on_handler_exceptionreturnsbool—trueremoves the handler from future invocations,falsekeeps it):swallow_event_errors_traits— logs viaLOG_CAUGHT_EXCEPTION()and swallows; all handlers are called regardless. Default.propagate_event_errors_traits— rethrows the exception, stopping remaining handlers (same aswinrt::event)failfast_event_errors_traits— callsFAIL_FAST_CAUGHT_EXCEPTION()on any handler exceptionrpc_resilient_event_errors_traits— for RPC/IPC disconnection errors (RPC_E_DISCONNECTED,RPC_S_SERVER_UNAVAILABLE,RPC_E_SERVER_DIED, etc.) logs and removes the broken handler; for all other errors logs and keeps the handlerEvent type:
winrt_event<T, Traits = swallow_event_errors_traits>— wraps each handler in a try/catch at registration time. WhenTraits::on_handler_exceptionreturnstrue, the handler is automatically removed from future invocations. Thread safety is inherited fromwinrt::event<T>. Internally usesshared_ptr<winrt::event<T>>so lambdas can safely self-remove viaweak_ptr.Usage
The interface mirrors
untyped_event/typed_event:operator()(handler)to subscribe,operator()(token)to unsubscribe,invoke(args...)to fire.Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.