microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.36k stars 678 forks source link

Crash in swap chain during shutdown due to teardown order #7924

Closed ackh closed 1 year ago

ackh commented 2 years ago

Describe the bug

I have an app that uses custom controls that inherit from SwapChainPanel to render DirectX content. Each custom control is shown on a dedicated page within a NavigationView. Switching the page in the NavigationControl destroys the previously shown SwapChainPanel-based control and creates an instance of the control to be shown.

Switching between the NavigationView pages worked fine when using the Windows App SDK 1.1.5 or earlier. However, after upgrading to the Windows App SDK 1.2 I'm getting an unhandled exception when the following method of Microsoft.UI.Xaml.h is called:

template <typename D> auto consume_Microsoft_UI_Xaml_IApplicationStatics<D>::Start(winrt::Microsoft::UI::Xaml::ApplicationInitializationCallback const& callback) const
{
    check_hresult(WINRT_IMPL_SHIM(winrt::Microsoft::UI::Xaml::IApplicationStatics)->Start(*(void**)(&callback)));
}

That exception simply states the following:

Unhandled exception at 0x00007FFC646AFDF2 (KernelBase.dll) in MyApp.exe: 0xC0000602:  A fail fast exception occurred. Exception handlers will not be invoked and the process will be terminated immediately.

The full stack trace looks as follows:

KernelBase.dll!00007ffc646afdf2()
dcompi.dll!00007ffc07c74259()
dcompi.dll!00007ffc07c25f81()
dcompi.dll!00007ffc07bd4003()
dcompi.dll!00007ffc07c29ea6()
dcompi.dll!00007ffc07be2576()
dcompi.dll!00007ffc07be2390()
dcompi.dll!00007ffc07c3b2dd()
Microsoft.ui.xaml.dll!00007ffbff427346()
Microsoft.ui.xaml.dll!00007ffbff4273d4()
Microsoft.ui.xaml.dll!00007ffbff0bde0e()
Microsoft.ui.xaml.dll!00007ffbff109010()
Microsoft.ui.xaml.dll!00007ffbff196f6b()
Microsoft.ui.xaml.dll!00007ffbff1972bd()
Microsoft.ui.xaml.dll!00007ffbff197120()
Microsoft.ui.xaml.dll!00007ffbff180e64()
Microsoft.ui.xaml.dll!00007ffbff17ff2a()
Microsoft.ui.xaml.dll!00007ffbff401534()
Microsoft.ui.xaml.dll!00007ffbff0bde0e()
Microsoft.ui.xaml.dll!00007ffbff109010()
Microsoft.ui.xaml.dll!00007ffbff196f6b()
Microsoft.ui.xaml.dll!00007ffbff1972bd()
Microsoft.ui.xaml.dll!00007ffbff197120()
Microsoft.ui.xaml.dll!00007ffbff180e64()
Microsoft.ui.xaml.dll!00007ffbff17ff2a()
Microsoft.ui.xaml.dll!00007ffbff7ac434()
Microsoft.ui.xaml.dll!00007ffbff0bde0e()
Microsoft.ui.xaml.dll!00007ffbff0bf3d2()
Microsoft.ui.xaml.dll!00007ffbff0bec2e()
Microsoft.ui.xaml.dll!00007ffbff0beb49()
Microsoft.ui.xaml.dll!00007ffbff1f149f()
Microsoft.ui.xaml.dll!00007ffbff1f13fd()
CoreMessagingXP.dll!00007ffc211873c8()
CoreMessagingXP.dll!00007ffc211875ce()
CoreMessagingXP.dll!00007ffc2118719b()
CoreMessagingXP.dll!00007ffc21161888()
CoreMessagingXP.dll!00007ffc2116175b()
CoreMessagingXP.dll!00007ffc2113ce30()
CoreMessagingXP.dll!00007ffc21109e64()
CoreMessagingXP.dll!00007ffc2110971c()
CoreMessagingXP.dll!00007ffc210fee77()
CoreMessagingXP.dll!00007ffc21101138()
CoreMessagingXP.dll!00007ffc211015e7()
CoreMessagingXP.dll!00007ffc211014d8()
CoreMessagingXP.dll!00007ffc211475ad()
CoreMessagingXP.dll!00007ffc21147532()
CoreMessagingXP.dll!00007ffc211473e3()
user32.dll!00007ffc64f7e858()
user32.dll!00007ffc64f7e3dc()
user32.dll!00007ffc64f90c03()
ntdll.dll!00007ffc66c70ef4()
win32u.dll!00007ffc64a41104()
user32.dll!00007ffc64f91b7e()
Microsoft.ui.xaml.dll!00007ffbff1f47da()
Microsoft.ui.xaml.dll!00007ffbff1f502c()
Microsoft.ui.xaml.dll!00007ffbff1f49be()
MyApp.exe!winrt::impl::consume_Microsoft_UI_Xaml_IApplicationStatics<winrt::Microsoft::UI::Xaml::IApplicationStatics>::Start(const winrt::Microsoft::UI::Xaml::ApplicationInitializationCallback & callback) Line 157   C++
MyApp.exe!winrt::Microsoft::UI::Xaml::Application::Start::__l2::<lambda_1>::operator()(const winrt::Microsoft::UI::Xaml::IApplicationStatics & f) Line 12146    C++
MyApp.exe!winrt::impl::factory_cache_entry<winrt::Microsoft::UI::Xaml::Application,winrt::Microsoft::UI::Xaml::IApplicationStatics>::call<`winrt::Microsoft::UI::Xaml::Application::Start'::`2'::<lambda_1> &>(winrt::Microsoft::UI::Xaml::Application::Start::__l2::<lambda_1> & callback) Line 6334   C++
MyApp.exe!winrt::impl::call_factory<winrt::Microsoft::UI::Xaml::Application,winrt::Microsoft::UI::Xaml::IApplicationStatics,`winrt::Microsoft::UI::Xaml::Application::Start'::`2'::<lambda_1>>(winrt::Microsoft::UI::Xaml::Application::Start::__l2::<lambda_1> && callback) Line 6357  C++
MyApp.exe!winrt::Microsoft::UI::Xaml::Application::Start(const winrt::Microsoft::UI::Xaml::ApplicationInitializationCallback & callback) Line 12147 C++
[External Code]

The problem I have is that I'm currently clueless how that stack trace is related to my own code because none of the code in the call stack is mine. How can I figure out what the actual problem is?

As mentioned, this behavior only occurs when using Windows App SDK 1.2. What has changed there that now raises such an exception compared to the Windows App SDK 1.1.5 and earlier?

Steps to reproduce the bug

Currently only reproducible in proprietary code.

Expected behavior

If such an exception is thrown there should be a hint what the underlying issue is. It's not obvious what is causing this.

Screenshots

No response

NuGet package version

WinUI 3 - Windows App SDK 1.2.0

Windows version

Windows 10 (21H2): Build 19044

Additional context

The following NuGet packages are used:

Microsoft.Windows.CppWinRT.2.0.220909.4 Microsoft.Windows.SDK.BuildTools.10.0.22000.196 Microsoft.WindowsAppSDK.1.1.5

Scottj1s commented 2 years ago

@ackh In lieu of a repro, can you provide the complete dump? Or download as many symbols as possible, to improve the stack?

Also, you might try the workaround in this issue, in case it's related: https://github.com/microsoft/WindowsAppSDK/issues/3117#issuecomment-1314945705

ackh commented 2 years ago

@Scottj1s Thanks for your reply. I have symbolicated the above stack trace and it looks as shown below. In addition, the memory dump of that state is available here.

KernelBase.dll!RaiseFailFastException()
dcompi.dll!Microsoft::WRL2::ContextRuntimeClass::NotifyObjectResurrected(void)
dcompi.dll!Microsoft::WRL2::NestableRuntimeClass::InternalAddRef()
dcompi.dll!Microsoft::UI::Composition::VisualCommon::ToApi<Microsoft::UI::Composition::IVisual>()
dcompi.dll!Microsoft::UI::Composition::Visual::Destroy()
dcompi.dll!Microsoft::WRL2::ContextRuntimeClass::ProcessDestroyWorkflow()
dcompi.dll!Microsoft::WRL2::ContextRuntimeClass::OnFinalRelease_NoLock()
dcompi.dll!Microsoft::WRL2::NestedWinRtImplements<Microsoft::UI::Composition::SpriteVisual,Microsoft::UI::Composition::ISpriteVisual,Microsoft::UI::Composition::ISpriteVisual2>::Release()
Microsoft.ui.xaml.dll!CSwapChainPanel::~CSwapChainPanel(void)
Microsoft.ui.xaml.dll!CSwapChainPanel::`vector deleting destructor'(unsigned int)
Microsoft.ui.xaml.dll!CDependencyObject::Release()
Microsoft.ui.xaml.dll!DirectUI::DependencyObject::DisconnectFrameworkPeerCore()
Microsoft.ui.xaml.dll!DirectUI::DependencyObject::DisconnectFrameworkPeer(unsigned int)
Microsoft.ui.xaml.dll!DirectUI::DependencyObject::EndShutdown(void)
Microsoft.ui.xaml.dll!DirectUI::DXamlCore::ShutdownAllPeers(void)
Microsoft.ui.xaml.dll!DirectUI::DXamlCore::CommonShutdown(void)
Microsoft.ui.xaml.dll!DirectUI::DXamlCore::DeinitializeInstance(void)
Microsoft.ui.xaml.dll!DirectUI::DXamlCore::Deinitialize(enum DeinitializationType)
Microsoft.ui.xaml.dll!DirectUI::WindowsXamlManager::XamlCore::Close(void)
Microsoft.ui.xaml.dll!Microsoft::WRL::Details::DelegateArgTraits<long (__cdecl ABI::Microsoft::UI::Dispatching::IDispatcherQueueHandler::*)(void)>::DelegateInvokeHelper<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<2>,ABI::Microsoft::UI::Dispatching::IDispatcherQueueHandler,Microsoft::WRL::FtmBase>,`DirectUI::WindowsXamlManager::EnqueueClose'::`2'::<lambda_1> &,1>::Invoke()
CoreMessagingXP.dll!Microsoft::UI::Dispatching::DispatcherQueue::DeferInvokeCallback(void *)
CoreMessagingXP.dll!CFlat::SehSafe::Execute<<lambda_a81ff790741c2a62f2197c2561f5fe49>>()
CoreMessagingXP.dll!Microsoft::CoreUI::ActionCallback::ImportAdapter$(class CFlat::Box$1<struct CFlat::FunctionPointerAndUserData$1<long > > *)
CoreMessagingXP.dll!Microsoft::CoreUI::Messaging::MessageSession::Callback_InvokeDeferInvoke(class Microsoft::CoreUI::ActionCallback *,struct System::UIntPtr)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::DeferredCall::Callback_Dispatch(void)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::DeferredCallDispatcher::Callback_OnDispatch(void)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::Dispatcher::Callback_DispatchNextItem(class Microsoft::CoreUI::Dispatch::DispatchItem *)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::Dispatcher::Callback_DispatchLoop(enum Microsoft::CoreUI::Dispatch::RunnablePriorityMask)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::EventLoop::Callback_RunCoreLoop(enum Microsoft::CoreUI::Dispatch::RunMode)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DrainCoreMessagingQueue(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatch(bool,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatchRaw(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool,void * *)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::DoWork(struct HWND__ *,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::HandleDispatchNotifyMessage(struct HWND__ *,unsigned __int64,__int64)
CoreMessagingXP.dll!Microsoft::CoreUI::Dispatch::UserAdapter::WindowProc(struct HWND__ *,unsigned int,unsigned __int64,__int64)
user32.dll!UserCallWinProcCheckWow()
user32.dll!DispatchMessageWorker()
Microsoft.ui.xaml.dll!DirectUI::FrameworkApplication::StartDesktop()
Microsoft.ui.xaml.dll!DirectUI::FrameworkApplicationFactory::Start()
MyApp.exe!winrt::impl::consume_Microsoft_UI_Xaml_IApplicationStatics<winrt::Microsoft::UI::Xaml::IApplicationStatics>::Start(const winrt::Microsoft::UI::Xaml::ApplicationInitializationCallback & callback) Line 157
MyApp.exe!winrt::Microsoft::UI::Xaml::Application::Start::__l2::<lambda_1>::operator()(const winrt::Microsoft::UI::Xaml::IApplicationStatics & f) Line 12146
MyApp.exe!winrt::impl::factory_cache_entry<winrt::Microsoft::UI::Xaml::Application,winrt::Microsoft::UI::Xaml::IApplicationStatics>::call<`winrt::Microsoft::UI::Xaml::Application::Start'::`2'::<lambda_1> &>(winrt::Microsoft::UI::Xaml::Application::Start::__l2::<lambda_1> & callback) Line 6334
MyApp.exe!winrt::impl::call_factory<winrt::Microsoft::UI::Xaml::Application,winrt::Microsoft::UI::Xaml::IApplicationStatics,`winrt::Microsoft::UI::Xaml::Application::Start'::`2'::<lambda_1>>(winrt::Microsoft::UI::Xaml::Application::Start::__l2::<lambda_1> && callback) Line 6357
MyApp.exe!winrt::Microsoft::UI::Xaml::Application::Start(const winrt::Microsoft::UI::Xaml::ApplicationInitializationCallback & callback) Line 12147
[External Code]
Scottj1s commented 2 years ago

@ackh Thanks - very helpful. Will pass this along to the appropriate owners.

Scottj1s commented 2 years ago

@gegao18 any ideas?

gegao18 commented 2 years ago

Thanks for the stack trace. This looks like a known potential crash on shutdown when resources get torn down in a bad order, and it's something we're working on for WinAppSDK 1.3.

Do you see this crash shortly after tearing down Xaml in your app or shutting it down? The workaround in this case would be disconnect the SwapChainPanel from the tree and making sure it's deleted before shutting down the rest of Xaml.

ackh commented 2 years ago

@gegao18 Yes, I'm seeing it in both cases, i.e. when tearing down XAML that host a SwapChainPanel and when shutting down the app. If you need additional information to get to the bottom of this let me know.

Scottj1s commented 1 year ago

@ackh The problem is understood and a solution is in the works

Internal issue: task.ms/42283983

Scottj1s commented 1 year ago

Fix will be available in Windows App SDK 1.3. Unfortunately, there is no known workaround.

ackh commented 1 year ago

Thanks, @Scottj1s. I'm looking forward to 1.3!

fredemmott commented 1 year ago

This looks like a known potential crash on shutdown when resources get torn down in a bad order,

Does the fix in 1.3 potentially also cover #7254? It's particularly reproducible if tearing down a swapchain immediatley after setting one up

fredemmott commented 1 year ago

@Scottj1s

Fix will be available in Windows App SDK 1.3. Unfortunately, there is no known workaround.

I seem to have found a workaround for #7254, and given the issue title here, it seems likely it will also work here:

DemoPage::DemoPage() noexcept {
  InitializeComponent();

  auto weakThis = get_weak();

  mDQC = DispatcherQueueController::CreateOnDedicatedThread();
  // Don't need a swapchain for crash, but do need independent input source
  mDQC.DispatcherQueue().TryEnqueue([weakThis]() noexcept {
    auto strongThis = weakThis.get();
    if (!strongThis) {
      return;
    }
    auto inputSource = strongThis->SwapChainPanel().CreateCoreIndependentInputSource(
      InputPointerSourceDeviceKinds::Mouse | InputPointerSourceDeviceKinds::Pen
      | InputPointerSourceDeviceKinds::Touch);
  });
}

winrt::fire_and_forget DemoPage::final_release(std::unique_ptr<DemoPage> self) {
  auto panel = self->SwapChainPanel();
  // Delete 'self'...
  self.reset();
  // Literally delay deletion of `panel`. 0 doesn't fix the crash, I think we just need
  // to have re-entered the message pump/event loop
  co_await winrt::resume_after(std::chrono::milliseconds(1));
  co_return;
}

This is working fine when navigating 100 times in a loop; previously it would reliably crash on iteration 2.

ackh commented 1 year ago

@Scottj1s @gegao18 I have retested this bug with release 1.3.230331000 and I'm now getting the following crash and call stack:

KernelBase.dll!RaiseFailFastException()    Unknown
dcompi.dll!Microsoft::WRL2::FailFast::_Do(void const *,struct _EXCEPTION_RECORD *,struct _CONTEXT *,char const *)   Unknown
dcompi.dll!Microsoft::WRL2::FailFast::Unexpected(char const *)  Unknown
dcompi.dll!Microsoft::WRL2::ContextRuntimeClass::ProcessDestroyWorkflow(bool,bool *)    Unknown
dcompi.dll!Microsoft::WRL2::ContextRuntimeClass::OnFinalRelease_NoLock(bool)    Unknown
dcompi.dll!Microsoft::WRL2::NestedWinRtImplements<Microsoft::UI::Composition::SpriteVisual,Microsoft::UI::Composition::ISpriteVisual,Microsoft::UI::Composition::ISpriteVisual2>::Release() Unknown
Microsoft.ui.xaml.dll!CSwapChainPanel::~CSwapChainPanel(void)   Unknown
Microsoft.ui.xaml.dll!CSwapChainPanel::`vector deleting destructor'(unsigned int)   Unknown
Microsoft.ui.xaml.dll!CDependencyObject::Release()  Unknown
Microsoft.ui.xaml.dll!DirectUI::DependencyObject::DisconnectFrameworkPeerCore() Unknown
Microsoft.ui.xaml.dll!DirectUI::DependencyObject::OnFinalRelease()  Unknown
Microsoft.ui.xaml.dll!ctl::ComBase::ReleaseImpl()   Unknown
MyLib.dll!winrt::Windows::Foundation::IUnknown::unconditional_release_ref() Line 2155   C++
MyLib.dll!winrt::Windows::Foundation::IUnknown::release_ref() Line 2150 C++
MyLib.dll!winrt::Windows::Foundation::IUnknown::~IUnknown() Line 2054   C++
MyLib.dll!winrt::Windows::Foundation::IInspectable::~IInspectable() C++
MyLib.dll!winrt::impl::root_implements_composing_outer<1>::~root_implements_composing_outer<1>()    C++
MyLib.dll!winrt::impl::root_implements<winrt::MyNamespace::implementation::BaseView,winrt::MyNamespace::BaseView,winrt::composing,winrt::Microsoft::UI::Xaml::IFrameworkElementOverrides,winrt::Microsoft::UI::Xaml::IUIElementOverrides>::~root_implements<winrt::MyNamespace::implementation::BaseView,winrt::MyNamespace::BaseView,winrt::composing,winrt::Microsoft::UI::Xaml::IFrameworkElementOverrides,winrt::Microsoft::UI::Xaml::IUIElementOverrides>() Line 7402  C++
MyLib.dll!winrt::implements<winrt::MyNamespace::implementation::BaseView,winrt::MyNamespace::BaseView,winrt::composing,winrt::Microsoft::UI::Xaml::IFrameworkElementOverrides,winrt::Microsoft::UI::Xaml::IUIElementOverrides>::~implements<winrt::MyNamespace::implementation::BaseView,winrt::MyNamespace::BaseView,winrt::composing,winrt::Microsoft::UI::Xaml::IFrameworkElementOverrides,winrt::Microsoft::UI::Xaml::IUIElementOverrides>()    C++
MyLib.dll!winrt::MyNamespace::implementation::BaseView_base<winrt::MyNamespace::implementation::BaseView>::~BaseView_base<winrt::MyNamespace::implementation::BaseView>()   C++
MyLib.dll!winrt::MyNamespace::implementation::BaseView::~BaseView() Line 30 C++
...

I would really appreciate if someone could look into this soon. It might be an issue that I cause, but how would I know?

anup-das commented 1 year ago

@ackh I am also facing the exact same issue. Kindly re-open the issue. Stack trace for crash at my end... Stack Trace.txt

Scottj1s commented 1 year ago

@ackh, @anup-das the latest stacks are a bit different from the original issue reported here. But they involve the same code, so reopening this issue and alerting owners.

Scottj1s commented 1 year ago

@ackh The engineer working on the second crash reported here has requested another dump:

@Scottj1s @gegao18 I have retested this bug with release 1.3.230331000 and I'm now getting the following crash and call stack:

Would you be able to provide one?

ackh commented 1 year ago

Sure, the dump is available here.

I'm trying to put together a DirectX sample that uses the SwapChainPanel the same way as my production code. I'm currently not sure how feasible that is but it would likely help in the future in case we encounter other issues related to the SwapChainPanel.

ackh commented 1 year ago

@Scottj1s I managed to create a sample with which the issue can be reproduced. This GitHub repository contains the code.

A few words regarding the content of the repository:

The code added by commit 97a6dfdc6342b351810742b34c15130c39faec67 is a packaged Windows App SDK 1.1.5 app that draws on two different SwapChainPanels using DirectX. When the application is started it looks as follows:

SwapChainPanelBugRepro1

In that state, clicking the "Square View" button destroys the view showing the triangle and then creates the view that is showing a rectangle:

SwapChainPanelBugRepro2

This is the expected behavior.

If the app is started from Visual Studio with the debugger attached, closing the app will result in an exception and the hint that there are memory leaks. That seems to be the case because the code enables the DirectX debug layer and terminating the app does not properly clean up the DirectX resources. That app behavior might need to be discussed in another thread but for the time being, it is prevented by commit c493673c7dd750d9734bd3bcf8faf570b867bb06.

Following on, commit a2b9071724600d3b12d77b3620fdfdaaa208d501 adds code that eventually causes the issue if any of the Windows App SDK 1.2 or 1.3 releases are used. Without that code, the issue is not reproducible.

Finally, commit 29897029cccba330ed2417267bfd0d037cec6d96 upgrades to the Windows App SDK 1.3.230602002. Starting the app in that state and switching views via "Square View" button results in the issue.

Could you notify the responsible developer about this sample? I can reproduce it 100% of the time so it should be straight forward to find and fix the actual root cause.

Scottj1s commented 1 year ago

@ackh the team believes the last issue related to swap chain teardown crashes was addressed in Windows App SDK 1.3.230724000. Can you please re-evaluate with that or a later version?

ackh commented 1 year ago

@Scottj1s I retested it with release 1.3.230724000 and the crash is no longer reproducible. A big thanks to everyone involved in fixing it, really appreciated!

@anup-das Can you check whether it works for you as well? If so, I propose to close this issue.

anup-das commented 1 year ago

@ackh, I have been testing this issue with every release of the WinAppSDK. I can confirm that the crash issue is no longer reproducible in any of the releases starting from 1.3.230724000 upto the latest 1.4.231008000

But there is another major issue. See video attached

https://github.com/microsoft/microsoft-ui-xaml/assets/63170829/97638091-56f3-483f-a5d2-0f71900dd991

SwapChainPanel resizing is extremely laggy with discrete graphics involving the PCIE bus for release builds. No issue with Debug builds :-)

I have a Intel integrated GPU + NVDIA GPU active on the system with Intel configured in SBIOS as the default display. If i disable the Intel Integrated GPU completely in SBIOS then also the issue is present. This issue has been there since the begining. Across the different releases of WinApp SDK since 1.3.230724000, I have tried all possible things including changing the NVIDIA driver version

I guess there is a bug hiding in the release build of the SDK and it has something to do with the lifted compositor in WinUI 3. I have lost the motivation for filing new issue. I am migrating my app back to Win32 :-(