Skip to content

Avoid reentrancy issues when dropping AppHost#19296

Merged
lhecker merged 3 commits intomainfrom
dev/lhecker/apphost-drop
Sep 1, 2025
Merged

Avoid reentrancy issues when dropping AppHost#19296
lhecker merged 3 commits intomainfrom
dev/lhecker/apphost-drop

Conversation

@lhecker
Copy link
Member

@lhecker lhecker commented Aug 28, 2025

tl;dr: ~Apphost() may pump the message loop.
That's no bueno. See comments in the diff.

Additionally, this PR enables _assertIsMainThread in
release to trace down mysterious crashes in those builds.

@lhecker lhecker added Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Terminal The new Windows Terminal. labels Aug 28, 2025
@github-project-automation github-project-automation bot moved this to To Cherry Pick in 1.24 Servicing Pipeline Aug 28, 2025
@carlos-zamora
Copy link
Member

Is there an issue this is linked to or that it closes?

@lhecker
Copy link
Member Author

lhecker commented Aug 29, 2025

No, this is going off of a hunch. It's related to a slight rise in crashes as reported by watson.

@lhecker lhecker merged commit 8d41ace into main Sep 1, 2025
19 checks passed
@lhecker lhecker deleted the dev/lhecker/apphost-drop branch September 1, 2025 13:33
@github-project-automation github-project-automation bot moved this to To Cherry Pick in 1.23 Servicing Pipeline Sep 5, 2025
@DHowett DHowett moved this from To Cherry Pick to Cherry Picked in 1.23 Servicing Pipeline Sep 5, 2025
DHowett pushed a commit that referenced this pull request Sep 5, 2025
tl;dr: ~Apphost() may pump the message loop.
That's no bueno. See comments in the diff.

Additionally, this PR enables `_assertIsMainThread` in
release to trace down mysterious crashes in those builds.

**BACKPORT NOTES**
I returned the `_assertIsMainThread` check to debug-only to remove the
assertion risk from production builds.

(cherry picked from commit 8d41ace)
Service-Card-Id: PVTI_lADOAF3p4s4AxadtzgebmmE
Service-Version: 1.23
@DHowett DHowett moved this from To Cherry Pick to Cherry Picked in 1.24 Servicing Pipeline Sep 5, 2025
DHowett pushed a commit that referenced this pull request Sep 5, 2025
tl;dr: ~Apphost() may pump the message loop.
That's no bueno. See comments in the diff.

Additionally, this PR enables `_assertIsMainThread` in
release to trace down mysterious crashes in those builds.

(cherry picked from commit 8d41ace)
Service-Card-Id: PVTI_lADOAF3p4s4BBcTlzgeJeYA
Service-Version: 1.24
DHowett added a commit that referenced this pull request Sep 29, 2025
The previous fix in #19296 moved the _destruction_ of AppHost into the
tail end after we manipulate the `_windows` vector; however, it kept the
part which calls into XAML (`Close`) before the `erase`. I suspect that
we still had some reentrancy issues, where we cached an iterator before
the list was modified by another window close event.

That is:

```mermaid
sequenceDiagram
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (a)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (b)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(b)
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(a)
```

Moving the `Close()` to after the `erase` ensures that there are no
cached iterators that survive beyond XAML pumping the message loop.

Fixes 8d41ace
DHowett added a commit that referenced this pull request Sep 30, 2025
The previous fix in #19296 moved the _destruction_ of AppHost into the
tail end after we manipulate the `_windows` vector; however, it kept the
part which calls into XAML (`Close`) before the `erase`. I suspect that
we still had some reentrancy issues, where we cached an iterator before
the list was modified by another window close event.

That is:

```mermaid
sequenceDiagram
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (a)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (b)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(b)
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(a)
```

Moving the `Close()` to after the `erase` ensures that there are no
cached iterators that survive beyond XAML pumping the message loop.

Fixes 8d41ace
DHowett added a commit that referenced this pull request Oct 8, 2025
The previous fix in #19296 moved the _destruction_ of AppHost into the
tail end after we manipulate the `_windows` vector; however, it kept the
part which calls into XAML (`Close`) before the `erase`. I suspect that
we still had some reentrancy issues, where we cached an iterator before
the list was modified by another window close event.

That is:

```mermaid
sequenceDiagram
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (a)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (b)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(b)
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(a)
```

Moving the `Close()` to after the `erase` ensures that there are no
cached iterators that survive beyond XAML pumping the message loop.

Fixes 8d41ace

(cherry picked from commit 5976de1)
Service-Card-Id: PVTI_lADOAF3p4s4AxadtzgfScoo
Service-Version: 1.23
DHowett added a commit that referenced this pull request Oct 8, 2025
The previous fix in #19296 moved the _destruction_ of AppHost into the
tail end after we manipulate the `_windows` vector; however, it kept the
part which calls into XAML (`Close`) before the `erase`. I suspect that
we still had some reentrancy issues, where we cached an iterator before
the list was modified by another window close event.

That is:

```mermaid
sequenceDiagram
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (a)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		Emperor->>Emperor: Close Window
		Emperor->>+AppHost: Close (b)
		AppHost->>XAML: Close
		XAML-->>Emperor: pump loop
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(b)
		AppHost->>-Emperor: Closed
		Emperor->>Emperor: erase(a)
```

Moving the `Close()` to after the `erase` ensures that there are no
cached iterators that survive beyond XAML pumping the message loop.

Fixes 8d41ace

(cherry picked from commit 5976de1)
Service-Card-Id: PVTI_lADOAF3p4s4BBcTlzgfScpM
Service-Version: 1.24
@DHowett DHowett moved this from Cherry Picked to Shipped in 1.23 Servicing Pipeline Jan 15, 2026
@DHowett DHowett moved this from Cherry Picked to Shipped in 1.24 Servicing Pipeline Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Terminal The new Windows Terminal.

Projects

Development

Successfully merging this pull request may close these issues.

2 participants