diff --git a/src/cascadia/TerminalApp/DebugTapConnection.cpp b/src/cascadia/TerminalApp/DebugTapConnection.cpp index 54f327b3e..0d84d8f05 100644 --- a/src/cascadia/TerminalApp/DebugTapConnection.cpp +++ b/src/cascadia/TerminalApp/DebugTapConnection.cpp @@ -21,8 +21,22 @@ namespace winrt::Microsoft::TerminalApp::implementation } void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {} ~DebugInputTapConnection() = default; - void Start() + winrt::fire_and_forget Start() { + // GH#11282: It's possible that we're about to be started, _before_ + // our paired connection is started. Both will get Start()'ed when + // their owning TermControl is finally laid out. However, if we're + // started first, then we'll immediately start printing to the other + // control as well, which might not have initialized yet. If we do + // that, we'll explode. + // + // Instead, wait here until the other connection is started too, + // before actually starting the connection to the client app. This + // will ensure both controls are initialized before the client app + // is. + co_await winrt::resume_background(); + _pairedTap->_start.wait(); + _wrappedConnection.Start(); } void WriteInput(hstring const& data) @@ -59,6 +73,9 @@ namespace winrt::Microsoft::TerminalApp::implementation void DebugTapConnection::Start() { // presume the wrapped connection is started. + + // This is explained in the comment for GH#11282 above. + _start.count_down(); } void DebugTapConnection::WriteInput(hstring const& data) diff --git a/src/cascadia/TerminalApp/DebugTapConnection.h b/src/cascadia/TerminalApp/DebugTapConnection.h index c5156afc4..56d509fbf 100644 --- a/src/cascadia/TerminalApp/DebugTapConnection.h +++ b/src/cascadia/TerminalApp/DebugTapConnection.h @@ -5,6 +5,7 @@ #include #include "../../inc/cppwinrt_utils.h" +#include namespace winrt::Microsoft::TerminalApp::implementation { @@ -36,6 +37,8 @@ namespace winrt::Microsoft::TerminalApp::implementation winrt::weak_ref _wrappedConnection; winrt::weak_ref _inputSide; + til::latch _start{ 1 }; + friend class DebugInputTapConnection; }; } diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index efcce89c8..9c3af6bc3 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1025,7 +1025,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation TerminalConnection::ConnectionState ControlCore::ConnectionState() const { - return _connection.State(); + return _connection ? _connection.State() : TerminalConnection::ConnectionState::Closed; } hstring ControlCore::Title()