Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix session persistence when the session ends #17714

Merged
merged 3 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions src/cascadia/Remoting/Monarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation

peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { ShowNotificationIconRequested.raise(*this, nullptr); });
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { HideNotificationIconRequested.raise(*this, nullptr); });
peasant.QuitAllRequested({ this, &Monarch::_handleQuitAll });

{
std::unique_lock lock{ _peasantsMutex };
Expand Down Expand Up @@ -134,7 +133,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - <none> used
// Return Value:
// - <none>
void Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/)
void Monarch::QuitAll()
{
if (_quitting.exchange(true, std::memory_order_relaxed))
{
Expand Down Expand Up @@ -166,12 +165,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
peasantSearch->second.Quit();
}
else
{
// Somehow we don't have our own peasant, this should never happen.
// We are trying to quit anyways so just fail here.
assert(peasantSearch != _peasants.end());
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/Remoting/Monarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation

uint64_t AddPeasant(winrt::Microsoft::Terminal::Remoting::IPeasant peasant);
void SignalClose(const uint64_t peasantId);
void QuitAll();

uint64_t GetNumberOfPeasants();

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/Remoting/Monarch.idl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ namespace Microsoft.Terminal.Remoting
void HandleActivatePeasant(WindowActivatedArgs args);
void SummonWindow(SummonWindowSelectionArgs args);
void SignalClose(UInt64 peasantId);
void QuitAll();

void SummonAllWindows();
Boolean DoesQuakeWindowExist();
Expand Down
16 changes: 0 additions & 16 deletions src/cascadia/Remoting/Peasant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,22 +260,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}

void Peasant::RequestQuitAll()
{
try
{
QuitAllRequested.raise(*this, nullptr);
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
TraceLoggingWrite(g_hRemotingProvider,
"Peasant_RequestQuit",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}

void Peasant::AttachContentToWindow(Remoting::AttachRequest request)
{
try
Expand Down
2 changes: 0 additions & 2 deletions src/cascadia/Remoting/Peasant.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
void RequestShowNotificationIcon();
void RequestHideNotificationIcon();
void RequestQuitAll();
void Quit();

void AttachContentToWindow(Remoting::AttachRequest request);
Expand All @@ -76,7 +75,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation

til::typed_event<> ShowNotificationIconRequested;
til::typed_event<> HideNotificationIconRequested;
til::typed_event<> QuitAllRequested;
til::typed_event<> QuitRequested;

til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::AttachRequest> AttachRequested;
Expand Down
2 changes: 0 additions & 2 deletions src/cascadia/Remoting/Peasant.idl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ namespace Microsoft.Terminal.Remoting

void RequestShowNotificationIcon();
void RequestHideNotificationIcon();
void RequestQuitAll();
void Quit();

void AttachContentToWindow(AttachRequest request);
Expand All @@ -95,7 +94,6 @@ namespace Microsoft.Terminal.Remoting

event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;

event Windows.Foundation.TypedEventHandler<Object, AttachRequest> AttachRequested;
Expand Down
12 changes: 12 additions & 0 deletions src/cascadia/Remoting/WindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,18 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
WindowClosed.raise(s, e);
}

void WindowManager::QuitAll()
{
if (_monarch)
{
try
{
_monarch.QuitAll();
}
CATCH_LOG()
}
}

void WindowManager::SignalClose(const Remoting::Peasant& peasant)
{
if (_monarch)
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/Remoting/WindowManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
Remoting::Peasant CreatePeasant(const Remoting::WindowRequestedArgs& args);

void SignalClose(const Remoting::Peasant& peasant);
void QuitAll();
void SummonWindow(const Remoting::SummonWindowSelectionArgs& args);
void SummonAllWindows();
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/Remoting/WindowManager.idl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Microsoft.Terminal.Remoting
Peasant CreatePeasant(WindowRequestedArgs args);

void SignalClose(Peasant p);
void QuitAll();

void UpdateActiveTabTitle(String title, Peasant p);

Expand Down
3 changes: 1 addition & 2 deletions src/cascadia/UnitTests_Remoting/RemotingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ namespace RemotingUnitTests
void Summon(const Remoting::SummonWindowBehavior& /*args*/) DIE;
void RequestShowNotificationIcon() DIE;
void RequestHideNotificationIcon() DIE;
void RequestQuitAll() DIE;
void Quit() DIE;
void AttachContentToWindow(Remoting::AttachRequest) DIE;
void SendContent(winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs) DIE;
Expand All @@ -94,7 +93,6 @@ namespace RemotingUnitTests
til::typed_event<winrt::Windows::Foundation::IInspectable, Remoting::SummonWindowBehavior> SummonRequested;
til::typed_event<> ShowNotificationIconRequested;
til::typed_event<> HideNotificationIconRequested;
til::typed_event<> QuitAllRequested;
til::typed_event<> QuitRequested;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::AttachRequest> AttachRequested;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs> SendContentRequested;
Expand All @@ -111,6 +109,7 @@ namespace RemotingUnitTests
void HandleActivatePeasant(Remoting::WindowActivatedArgs /*args*/) DIE;
void SummonWindow(Remoting::SummonWindowSelectionArgs /*args*/) DIE;
void SignalClose(uint64_t /*peasantId*/) DIE;
void QuitAll() DIE;

void SummonAllWindows() DIE;
bool DoesQuakeWindowExist() DIE;
Expand Down
67 changes: 48 additions & 19 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#include <TerminalThemeHelpers.h>

#include <til/latch.h>

using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml;
Expand Down Expand Up @@ -348,9 +350,29 @@ void AppHost::Initialize()
});

_windowCallbacks.AutomaticShutdownRequested = _window->AutomaticShutdownRequested([this]() {
// Raised when the OS is beginning an update of the app. We will quit,
// to save our state, before the OS manually kills us.
_quit();
// This is the WM_ENDSESSION handler.
// The event is raised when the user is logged out, because the system is rebooting, etc.
// Due to the design of WM_ENDSESSION, returning from the message indicates to the OS that it's fine to
// terminate us at any time. Luckily Windows has never heavily relied on message passing or asynchronous
// eventing in any of its UI frameworks. It also was clearly impossible to use WaitForMultipleObjects with
// bWaitAll=TRUE and a timeout to wait for all applications to exit cleanly.
// As such we attempt to synchronously shut down the app here. Otherwise, it could just call _quit().

const auto state = ApplicationState::SharedInstance();

state.PersistedWindowLayouts(nullptr);

// A duplicate of AppHost::_QuitRequested().
if (_appLogic && _windowLogic && _appLogic.ShouldUsePersistedLayout())
{
_windowLogic.PersistState();
}

_windowManager.SignalClose(_peasant);
_windowManager.QuitAll();

// Ensure to write the state.json before we get TerminateProcess()d by the OS (Thanks!).
state.Flush();
});

// Load bearing: make sure the PropertyChanged handler is added before we
Expand Down Expand Up @@ -440,7 +462,7 @@ winrt::fire_and_forget AppHost::_quit()
co_await winrt::resume_background();

ApplicationState::SharedInstance().PersistedWindowLayouts(nullptr);
peasant.RequestQuitAll();
_windowManager.QuitAll();
}

void AppHost::_revokeWindowCallbacks()
Expand Down Expand Up @@ -1157,25 +1179,32 @@ void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectab
}

// Raised from our Peasant. We handle by propagating the call to our terminal window.
winrt::fire_and_forget AppHost::_QuitRequested(const winrt::Windows::Foundation::IInspectable&,
const winrt::Windows::Foundation::IInspectable&)
void AppHost::_QuitRequested(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&)
{
auto weakThis{ weak_from_this() };
// Need to be on the main thread to close out all of the tabs.
co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher());
// We process the shutdown synchronously here, because otherwise the
// AutomaticShutdownRequested() logic wouldn't run synchronously either.
til::latch latch{ 1 };

const auto strongThis = weakThis.lock();
if (!strongThis)
{
co_return;
}
_windowLogic.GetRoot().Dispatcher().RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [&latch, weakThis = weak_from_this()]() {
const auto countDownOnExit = wil::scope_exit([&latch] {
latch.count_down();
});

if (_appLogic && _windowLogic && _appLogic.ShouldUsePersistedLayout())
{
_windowLogic.PersistState();
}
const auto self = weakThis.lock();
if (!self)
{
return;
}

if (self->_appLogic && self->_windowLogic && self->_appLogic.ShouldUsePersistedLayout())
{
self->_windowLogic.PersistState();
}

PostQuitMessage(0);
});

PostQuitMessage(0);
latch.wait();
}

// Raised from TerminalWindow. We handle by bubbling the request to the window manager.
Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/WindowsTerminal/AppHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ class AppHost : public std::enable_shared_from_this<AppHost>
void _SystemMenuChangeRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::TerminalApp::SystemMenuChangeArgs& args);

winrt::fire_and_forget _QuitRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
void _QuitRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);

void _RequestQuitAll(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
Expand Down
Loading