Fix crash when closing panes very quickly (#17450)

#17358 introduced a bug where if you open/close panes very rapidly
Terminal will crash. This was because `_content` was being set to `null`
and then a `Close` event was being emitted, but several functions
attempt to access the pane's `_content` as part of the close routine.
For example, `TerminalTab` tries to update the `TaskbarProgress` every
time a pane is closed and as part of that update sequence it queries the
pane - which has `null` content now - for the taskbar progress,
resulting in a crash. This PR fixes that crash.

Refs #17358
This commit is contained in:
PankajBhojwani 2024-06-20 09:07:40 -07:00 committed by GitHub
parent a80539c2f7
commit 5d46e317b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1711,7 +1711,9 @@ void Pane::_SetupChildCloseHandlers()
IPaneContent Pane::_takePaneContent() IPaneContent Pane::_takePaneContent()
{ {
_closeRequestedRevoker.revoke(); _closeRequestedRevoker.revoke();
return std::move(_content); // we cannot return std::move(_content) because we don't want _content to be null,
// since _content gets accessed even after Close is called
return _content;
} }
// This method safely sets the content of the Pane. It'll ensure to revoke and // This method safely sets the content of the Pane. It'll ensure to revoke and
@ -1721,15 +1723,14 @@ void Pane::_setPaneContent(IPaneContent content)
{ {
// The IPaneContent::Close() implementation may be buggy and raise the CloseRequested event again. // The IPaneContent::Close() implementation may be buggy and raise the CloseRequested event again.
// _takePaneContent() avoids this as it revokes the event handler. // _takePaneContent() avoids this as it revokes the event handler.
if (const auto c = _takePaneContent()) if (_takePaneContent())
{ {
c.Close(); _content.Close();
} }
_content = std::move(content); if (content)
if (_content)
{ {
_content = std::move(content);
_closeRequestedRevoker = _content.CloseRequested(winrt::auto_revoke, [this](auto&&, auto&&) { Close(); }); _closeRequestedRevoker = _content.CloseRequested(winrt::auto_revoke, [this](auto&&, auto&&) { Close(); });
} }
} }