Fix DesktopWindowXamlSource related crashes when closing a window#15338
Conversation
| // _window callbacks don't need to be treated this way, because: | ||
| // * IslandWindow isn't a WinRT type (so it doesn't have neat revokers like this) | ||
| // * This particular bug scenario applies when we've already freed the window. |
There was a problem hiding this comment.
In short, these 3 lines are wrong. 😄
| { | ||
| _showHideWindowThrottler->Run(args.ShowOrHide()); | ||
| } | ||
| _showHideWindowThrottler->Run(args.ShowOrHide()); |
There was a problem hiding this comment.
This if check is a common pattern we got with our throttled funcs. It's generally not very safe, because it fails to work as soon as Run() is called from a background thread. This code still works correctly, because the _revokers are nulled out before the _showHideWindowThrottler is reset.
fa31979 to
0801694
Compare
| // - args: the arguments specifying how to set the display status to ShowWindow for our window handle | ||
| winrt::fire_and_forget TerminalPage::_ShowWindowChangedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args) | ||
| { | ||
| co_await resume_foreground(Dispatcher()); |
There was a problem hiding this comment.
With the if check for _showHideWindowThrottler removed, we can safely drop this resume_foreground. It's also a nice safety fix, because it doesn't hold onto this strongly.
0801694 to
6b73290
Compare
| // Avoid further callbacks into XAML/WinUI-land after we've Close()d the DesktopWindowXamlSource | ||
| // inside `IslandWindow::Close()`. XAML thanks us for doing that by not crashing. Thank you XAML. | ||
| SetWindowLongPtr(_dragBarWindow.get(), GWLP_USERDATA, 0); | ||
| IslandWindow::Close(); |
There was a problem hiding this comment.
Without this, NonClientIslandWindow would crash here every single time I close a window:
| // - sender (not used) | ||
| // - args: the arguments specifying how to set the display status to ShowWindow for our window handle | ||
| winrt::fire_and_forget TerminalPage::_ShowWindowChangedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args) | ||
| void TerminalPage::_ShowWindowChangedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args) |
There was a problem hiding this comment.
note that changing this from a coroutine means that the excess copies on the arguments are not required. you could change them to const&
| // - sender (not used) | ||
| // - args: the arguments specifying how to set the display status to ShowWindow for our window handle | ||
| void TerminalPage::_ShowWindowChangedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args) | ||
| void TerminalPage::_ShowWindowChangedHandler(const IInspectable& /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args) |
There was a problem hiding this comment.
you only fixed the first arg..!
…5338) XAML/WinUI may pump the event loop internally. One of the functions that does this right now is `DesktopWindowXamlSource::Close()`. This is problematic in the previous code, because we'd set `_window` to `nullptr` before calling `Close()` and so any of the `IslandWindow` callbacks may be invoked during shutdown, which then try to potentially access `_window` and end up crashing. This commit fixes the issue by simply not nulling out the `_window` and calling `Close()` directly. Furthermore, `NonClientIslandWindow` may directly access WinUI objects in its message handlers which also crashes. I've had this happen roughly ~1% of my test exits in a debug build and every single time on a (artificial) very slow CPU. ## Validation Steps Performed * Closing a window destroys the rendering instance ✅ (cherry picked from commit ba39db5) Service-Card-Id: 89191262 Service-Version: 1.18
XAML/WinUI may pump the event loop internally. One of the functions
that does this right now is
DesktopWindowXamlSource::Close().This is problematic in the previous code, because we'd set
_windowto
nullptrbefore callingClose()and so any of theIslandWindowcallbacks may be invoked during shutdown, which then try to potentially
access
_windowand end up crashing. This commit fixes the issue bysimply not nulling out the
_windowand callingClose()directly.Furthermore,
NonClientIslandWindowmay directly access WinUIobjects in its message handlers which also crashes.
I've had this happen roughly ~1% of my test exits in a debug build
and every single time on a (artificial) very slow CPU.
Validation Steps Performed