Windows Terminal can crash if a tab is closed while data is being output #12006

Open
opened 2026-01-31 03:03:44 +00:00 by claunia · 0 comments
Owner

Originally created by @j4james on GitHub (Jan 10, 2021).

Environment

Windows build number: Version 10.0.18363.1256
Windows Terminal version (if applicable): Commit 49d008537f

Steps to reproduce

This is rather difficult to reproduce, but here is one sequence of events that is known to trigger it sometimes.

  1. Open Windows Terminal.
  2. Open a second tab with a bash shell.
  3. Output a large file (e.g. cat /mnt/c/Windows/explorer.exe).
  4. While the content is still being output, close the tab.
  5. Repeat steps 2 to 4 until it crashes.

Expected behavior

The tab should always be able close without crashing the app.

Actual behavior

Sometimes closing the tab will cause Windows Terminal to terminate with an unhandled exception.

The problem is that the TerminalControl is trying to process output when it has already been destroyed in the main thread (when the tab was closed). The exact location of the crash will vary, but it's quite often inside the Cursor::_RedrawCursorAlways method, triggered from somewhere like Terminal::_AdjustCursorPosition when adjusting the cursor position.

The reason it doesn't crash all the time, is because the renderer is often going to be painting a frame, in which case it will have grabbed the console lock, so the TerminalConnection thread wouldn't be able to output anything. And while the renderer is painting the frame, the shutdown will be blocked in the Renderer::TriggerTeardown call while waiting for the _hPaintCompletedEvent.

If you get the timing just right, though, the frame will have just finished painting, so the _hPaintCompletedEvent will have been set, and the console won't be locked. The TerminalConnection thread would then be free to grab the lock and start processing output, and the main thread wouldn't need to wait on _hPaintCompletedEvent, so could happily kill the TerminalControl while it is still in use.

Bottom line is I think we need another lock somewhere in the shutdown sequence.

Originally created by @j4james on GitHub (Jan 10, 2021). # Environment Windows build number: Version 10.0.18363.1256 Windows Terminal version (if applicable): Commit 49d008537f0bb73c8bfc85df773a46a2b3e9ac79 # Steps to reproduce This is rather difficult to reproduce, but here is one sequence of events that is known to trigger it sometimes. 1. Open Windows Terminal. 2. Open a second tab with a bash shell. 3. Output a large file (e.g. `cat /mnt/c/Windows/explorer.exe`). 4. While the content is still being output, close the tab. 5. Repeat steps 2 to 4 until it crashes. # Expected behavior The tab should always be able close without crashing the app. # Actual behavior Sometimes closing the tab will cause Windows Terminal to terminate with an unhandled exception. The problem is that the `TerminalControl` is trying to process output when it has already been destroyed in the main thread (when the tab was closed). The exact location of the crash will vary, but it's quite often inside the `Cursor::_RedrawCursorAlways` method, triggered from somewhere like `Terminal::_AdjustCursorPosition` when adjusting the cursor position. The reason it doesn't crash all the time, is because the renderer is often going to be painting a frame, in which case it will have grabbed the console lock, so the `TerminalConnection` thread wouldn't be able to output anything. And while the renderer is painting the frame, the shutdown will be blocked in the `Renderer::TriggerTeardown` call while waiting for the `_hPaintCompletedEvent`. If you get the timing just right, though, the frame will have just finished painting, so the `_hPaintCompletedEvent` will have been set, and the console won't be locked. The `TerminalConnection` thread would then be free to grab the lock and start processing output, and the main thread wouldn't need to wait on `_hPaintCompletedEvent`, so could happily kill the `TerminalControl` while it is still in use. Bottom line is I think we need another lock somewhere in the shutdown sequence.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#12006