diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index e6751469e30..e81ccf049b8 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -34,26 +34,6 @@ WindowEmperor::WindowEmperor() noexcept : }); _dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread(); - - // BODGY - // - // There's a mysterious crash in XAML on Windows 10 if you just let the App - // get dtor'd. By all accounts, it doesn't make sense. To mitigate this, we - // need to intentionally leak a reference to our App. Crazily, if you just - // let the app get cleaned up with the rest of the process when the process - // exits, then it doesn't crash. But if you let it get explicitly dtor'd, it - // absolutely will crash on exit. - // - // GH#15410 has more details. - - auto a{ _app }; - ::winrt::detach_abi(a); -} - -WindowEmperor::~WindowEmperor() -{ - _app.Close(); - _app = nullptr; } void _buildArgsFromCommandline(std::vector& args) @@ -78,7 +58,7 @@ void _buildArgsFromCommandline(std::vector& args) } } -bool WindowEmperor::HandleCommandlineArgs(int nCmdShow) +void WindowEmperor::HandleCommandlineArgs(int nCmdShow) { std::vector args; _buildArgsFromCommandline(args); @@ -97,13 +77,13 @@ bool WindowEmperor::HandleCommandlineArgs(int nCmdShow) const Remoting::CommandlineArgs eventArgs{ args, cwd, gsl::narrow_cast(nCmdShow), GetEnvironmentStringsW() }; const auto isolatedMode{ _app.Logic().IsolatedMode() }; const auto result = _manager.ProposeCommandline(eventArgs, isolatedMode); + int exitCode = 0; - const bool makeWindow = result.ShouldCreateWindow(); - if (makeWindow) + if (result.ShouldCreateWindow()) { _createNewWindowThread(Remoting::WindowRequestedArgs{ result, eventArgs }); - _becomeMonarch(); + WaitForWindows(); } else { @@ -111,11 +91,16 @@ bool WindowEmperor::HandleCommandlineArgs(int nCmdShow) if (!res.Message.empty()) { AppHost::s_DisplayMessageBox(res); - std::quick_exit(res.ExitCode); } + exitCode = res.ExitCode; } - return makeWindow; + // There's a mysterious crash in XAML on Windows 10 if you just let _app get destroyed (GH#15410). + // We also need to ensure that all UI threads exit before WindowEmperor leaves the scope on the main thread (MSFT:46744208). + // Both problems can be solved and the shutdown accelerated by using TerminateProcess. + // std::exit(), etc., cannot be used here, because those use ExitProcess for unpackaged applications. + TerminateProcess(GetCurrentProcess(), gsl::narrow_cast(exitCode)); + __assume(false); } void WindowEmperor::WaitForWindows() @@ -568,15 +553,6 @@ LRESULT WindowEmperor::_messageHandler(UINT const message, WPARAM const wParam, // we'll undoubtedly crash. winrt::fire_and_forget WindowEmperor::_close() { - { - auto fridge{ _oldThreads.lock() }; - for (auto& window : *fridge) - { - window->ThrowAway(); - } - fridge->clear(); - } - // Important! Switch back to the main thread for the emperor. That way, the // quit will go to the emperor's message pump. co_await wil::resume_foreground(_dispatcher); diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.h b/src/cascadia/WindowsTerminal/WindowEmperor.h index 874a0af7a8e..524a8a3d534 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.h +++ b/src/cascadia/WindowsTerminal/WindowEmperor.h @@ -24,10 +24,9 @@ class WindowEmperor : public std::enable_shared_from_this { public: WindowEmperor() noexcept; - ~WindowEmperor(); void WaitForWindows(); - bool HandleCommandlineArgs(int nCmdShow); + void HandleCommandlineArgs(int nCmdShow); private: void _createNewWindowThread(const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args); diff --git a/src/cascadia/WindowsTerminal/main.cpp b/src/cascadia/WindowsTerminal/main.cpp index 7789617030d..033f247f46d 100644 --- a/src/cascadia/WindowsTerminal/main.cpp +++ b/src/cascadia/WindowsTerminal/main.cpp @@ -115,8 +115,5 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int nCmdShow) winrt::init_apartment(winrt::apartment_type::single_threaded); const auto emperor = std::make_shared<::WindowEmperor>(); - if (emperor->HandleCommandlineArgs(nCmdShow)) - { - emperor->WaitForWindows(); - } + emperor->HandleCommandlineArgs(nCmdShow); }