Repository: microsoft/terminal (language: cpp)

Issue:
The SignalTextChanged crash isn't actually fixed
FYI I just got a crash in `RaiseAutomationEventImpl` passing through `SignalTextChanged`, which seems similar to the one shown in https://github.com/microsoft/terminal/issues/13357#issuecomment-1163015484. This occurred while shutting down the terminal, so I'm assuming I wouldn't have noticed usually, but I happened to be in the debugger at the time.

I'm branched off of 3e6abd37df192d969088188ce836edbf645b13b4, which includes PR #13876, so that doesn't appear to have helped. I do have some local changes, so it's possible that may be a factor, but I don't think that's likely.

The exception was:
```
Unhandled exception at 0x00007FFE52AADA82 (Windows.UI.Xaml.dll) in WindowsTerminal.exe: 0xC0000005: Access violation reading location 0x0000000000000010.
```

And this was the stack trace:
```
>	Windows.UI.Xaml.dll!DirectUI::AutomationPeer::RaiseAutomationEventImpl(Windows::UI::Xaml::Automation::Peers::AutomationEvents eventId) Line 813	C++
 	Windows.UI.Xaml.dll!DirectUI::AutomationPeerGenerated::RaiseAutomationEvent(Windows::UI::Xaml::Automation::Peers::AutomationEvents eventId) Line 1980	C++
 	Microsoft.Terminal.Control.dll!winrt::Microsoft::Terminal::Control::implementation::TermControlAutomationPeer::SignalTextChanged::__l2::<lambda_1>::operator()() Line 166	C++
 	Microsoft.Terminal.Control.dll!winrt::impl::delegate<winrt::Windows::UI::Core::DispatchedHandler,`winrt::Microsoft::Terminal::Control::implementation::TermControlAutomationPeer::SignalTextChanged'::`2'::<lambda_1>>::Invoke() Line 1136	C++
 	[External Code]	
 	[Inline Frame] WindowsTerminal.exe!winrt::impl::consume_Windows_Foundation_IClosable<winrt::TerminalApp::App>::Close() Line 121	C++
 	WindowsTerminal.exe!AppHost::~AppHost() Line 149	C++
 	WindowsTerminal.exe!wWinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, wchar_t * __formal, int __formal) Line 193	C++
 	[External Code]	
```

I poked about in the local variables for a bit to see if I could spot anything obviously wrong, but I'm afraid I don't understand the code well enough to make a meaningful assessment. A lot of fields said "Object uninitialized or information unavailable", but I suspect that may just be a release build thing.

_Originally posted by @j4james in https://github.com/microsoft/terminal/issues/13357#issuecomment-1242812664_


Discussion / hints:

Fix patch:
diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp
index 1f118c75385..7cfe8cbdc4b 100644
--- a/src/cascadia/TerminalControl/TermControl.cpp
+++ b/src/cascadia/TerminalControl/TermControl.cpp
@@ -1990,6 +1990,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
         if (!_IsClosing())
         {
             _closing = true;
+            if (_automationPeer)
+            {
+                auto autoPeerImpl{ winrt::get_self<implementation::TermControlAutomationPeer>(_automationPeer) };
+                autoPeerImpl->Close();
+            }
 
             _RestorePointerCursorHandlers(*this, nullptr);
 
diff --git a/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp b/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp
index 41c55b37640..e9147a77b73 100644
--- a/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp
+++ b/src/cascadia/TerminalControl/TermControlAutomationPeer.cpp
@@ -117,6 +117,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
         }
     }
 
+    void TermControlAutomationPeer::Close()
+    {
+        // GH#13978: If the TermControl has already been removed from the UI tree, XAML might run into weird bugs.
+        // This will prevent the `dispatcher.RunAsync` calls below from raising UIA events on the main thread.
+        _termControl = {};
+    }
+
     // Method Description:
     // - Signals the ui automation client that the terminal's selection has changed and should be updated
     // Arguments:
diff --git a/src/cascadia/TerminalControl/TermControlAutomationPeer.h b/src/cascadia/TerminalControl/TermControlAutomationPeer.h
index e8e62cf953c..be4351fdc15 100644
--- a/src/cascadia/TerminalControl/TermControlAutomationPeer.h
+++ b/src/cascadia/TerminalControl/TermControlAutomationPeer.h
@@ -49,6 +49,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
         void UpdateControlBounds();
         void SetControlPadding(const Core::Padding padding);
         void RecordKeyEvent(const WORD vkey);
+        void Close();
 
 #pragma region FrameworkElementAutomationPeer
         hstring GetClassNameCore() const;


Test patch: