Creating new processes in new Windows Terminals somehow crashes all instances of Windows Terminal when those processes exit #23367

Closed
opened 2026-01-31 08:40:11 +00:00 by claunia · 7 comments
Owner

Originally created by @DavidSpickett on GitHub (Jun 18, 2025).

Windows Terminal version

1.22.11141.0

Windows build number

10.0.22631.5335

Other Software

I first discovered this issue in LLDB's unit tests - https://github.com/llvm/llvm-project/issues/144077.

This report includes a standalone reproducer that requires no lldb code. The example is a bit weird though as it is converted from several layers of wrapper code and Gtest macros, so don't pay too much attention to the logic of what the reproducer is doing, or how things are named.

Steps to reproduce

Note that I am on Windows on Arm, I have not been able to try this on x64.

  • Download test.zip
  • Extract the test.cpp file inside
  • cl.exe test.cpp to compile the example, should produce test.exe. (if you compile this to another name, you will have to change the way argv0 is handled)
  • Open a Windows Terminal instance, can be anything, Powershell or cmd, whatever. Leave this somewhere visible on screen (it being visible is just so you can see the bug happening, it doesn't happen because it's visible).
  • Open a conhost and navigate to the location of the test.cpp file.
  • In the conhost run test.exe.
  • test.exe will spawn some new processes in additional Windows Terminal windows.
  • They will persist for a few seconds, stop responding then disappear.
  • The original Windows Terminal instance you opened at the start will also close, without you having told it to.
  • The test.exe will finish with exit code 0 as expected, and the conhost remains open.

Expected Behavior

I expect that the new terminals would be created and then disappear once those processes finish. Even if they finish by crashing, that should not take down unrelated Windows Terminal instances.

Actual Behavior

When the spawned processes end, every instance of Windows Terminal stops responding and then crashes.

I attached Visual Studio to the manually opened instance of Windows Terminal and when it crashed I got:

Exception thrown at 0x00007FF95D71DF0C (Microsoft.Terminal.Control.dll) in WindowsTerminal.exe: 0xC0000005: Access violation reading location 0x000000000000002C.

Call stack:

Microsoft.Terminal.Control.dll!00007ff95d71df0c()
Microsoft.Terminal.Control.dll!00007ff95d7464cc()
Microsoft.Terminal.Control.dll!00007ff95d766cd4()
TerminalConnection.dll!00007ff963f49554()
TerminalConnection.dll!00007ff963f47ebc()
TerminalConnection.dll!00007ff963f6afe8()
TerminalConnection.dll!00007ff963f6a4f8()
kernel32.dll!00007ff99e0622d0()
ntdll.dll!00007ff9a04f5b2c()

Disassembly:

   00007FF95D71DF08  mov         x19,x0  
>> 00007FF95D71DF0C  ldr         w8,[x19, #0x2C]  
   00007FF95D71DF10  mov         x24,x0  
   00007FF95D71DF14  stp         xzr,xzr,[x19,#0x48]

Registers:

 X0 = 0000000000000000  X1 = 00000277332AC9B0  X2 = 0000000000000017  X3 = 0000000000000000
 X4 = 0000000000000000  X5 = FFFFFFFFF3EB46AA  X6 = 0000000000000001  X7 = 000000007FFE6000
 X8 = 000000A9405DF5F0  X9 = 0000027731BAC060 X10 = 0000000000000000 X11 = 0000000000000000
X12 = 0000008F2AB968AB X13 = 0000000000000000 X14 = 0000000000000000 X15 = 00007FF95D746450
IP0 = 000064C71DACC59D IP1 = FFFF9BE222B12F33 X18 = 000000A93E4A0000 X19 = 0000000000000000
X20 = 0000000000000001 X21 = 0000000000000017 X22 = 000000A9405DF5A0 X23 = 00000277332AC9B0
X24 = 0000027731BF0260 X25 = 0000000000989680 X26 = 000000A9405DF640 X27 = 00007FF963F993A4
X28 = 0000000000000000  FP = 000000A9405DF4E0  LR = 00007FF95D71DEF8  SP = 000000A9405DF490
 PC = 00007FF95D71DF0C

Note that x19 is 0, so some pointer to a structure or class is nullptr here.

The tests might not be behaving as they should, but given the crash is inside Windows Terminal, I don't think it should lead to all the terminal windows being closed.

The test exe doesn't fail either, I didn't notice this bug because lldb tests failed, I just happened to reproduce some other failure inside a Windows Terminal and it crashed then. I think our buildbots are using conhost, which hid the issue.

C:\Users\tcwg>.\test.exe

C:\Users\tcwg>echo %errorlevel%
0

Random observations:

  • This does not crash conhost or other conhost instances you happen to have open.
  • Admin instances of Windows Terminal do not crash when the non-admin ones do.
Originally created by @DavidSpickett on GitHub (Jun 18, 2025). ### Windows Terminal version 1.22.11141.0 ### Windows build number 10.0.22631.5335 ### Other Software I first discovered this issue in LLDB's unit tests - https://github.com/llvm/llvm-project/issues/144077. This report includes a standalone reproducer that requires no lldb code. The example is a bit weird though as it is converted from several layers of wrapper code and Gtest macros, so don't pay too much attention to the logic of what the reproducer is doing, or how things are named. ### Steps to reproduce Note that I am on Windows on Arm, I have not been able to try this on x64. * Download [test.zip](https://github.com/user-attachments/files/20793387/test.zip) * Extract the test.cpp file inside * `cl.exe test.cpp` to compile the example, should produce `test.exe`. (if you compile this to another name, you will have to change the way argv0 is handled) * Open a Windows Terminal instance, can be anything, Powershell or cmd, whatever. Leave this somewhere visible on screen (it being visible is just so you can see the bug happening, it doesn't happen *because* it's visible). * Open a conhost and navigate to the location of the test.cpp file. * In the **conhost** run `test.exe`. * `test.exe` will spawn some new processes in additional Windows Terminal windows. * They will persist for a few seconds, stop responding then disappear. * The original Windows Terminal instance you opened at the start will also close, without you having told it to. * The `test.exe` will finish with exit code 0 as expected, and the conhost remains open. ### Expected Behavior I expect that the new terminals would be created and then disappear once those processes finish. Even if they finish by crashing, that should not take down unrelated Windows Terminal instances. ### Actual Behavior When the spawned processes end, every instance of Windows Terminal stops responding and then crashes. I attached Visual Studio to the manually opened instance of Windows Terminal and when it crashed I got: ``` Exception thrown at 0x00007FF95D71DF0C (Microsoft.Terminal.Control.dll) in WindowsTerminal.exe: 0xC0000005: Access violation reading location 0x000000000000002C. ``` Call stack: ``` Microsoft.Terminal.Control.dll!00007ff95d71df0c() Microsoft.Terminal.Control.dll!00007ff95d7464cc() Microsoft.Terminal.Control.dll!00007ff95d766cd4() TerminalConnection.dll!00007ff963f49554() TerminalConnection.dll!00007ff963f47ebc() TerminalConnection.dll!00007ff963f6afe8() TerminalConnection.dll!00007ff963f6a4f8() kernel32.dll!00007ff99e0622d0() ntdll.dll!00007ff9a04f5b2c() ``` Disassembly: ``` 00007FF95D71DF08 mov x19,x0 >> 00007FF95D71DF0C ldr w8,[x19, #0x2C] 00007FF95D71DF10 mov x24,x0 00007FF95D71DF14 stp xzr,xzr,[x19,#0x48] ``` Registers: ``` X0 = 0000000000000000 X1 = 00000277332AC9B0 X2 = 0000000000000017 X3 = 0000000000000000 X4 = 0000000000000000 X5 = FFFFFFFFF3EB46AA X6 = 0000000000000001 X7 = 000000007FFE6000 X8 = 000000A9405DF5F0 X9 = 0000027731BAC060 X10 = 0000000000000000 X11 = 0000000000000000 X12 = 0000008F2AB968AB X13 = 0000000000000000 X14 = 0000000000000000 X15 = 00007FF95D746450 IP0 = 000064C71DACC59D IP1 = FFFF9BE222B12F33 X18 = 000000A93E4A0000 X19 = 0000000000000000 X20 = 0000000000000001 X21 = 0000000000000017 X22 = 000000A9405DF5A0 X23 = 00000277332AC9B0 X24 = 0000027731BF0260 X25 = 0000000000989680 X26 = 000000A9405DF640 X27 = 00007FF963F993A4 X28 = 0000000000000000 FP = 000000A9405DF4E0 LR = 00007FF95D71DEF8 SP = 000000A9405DF490 PC = 00007FF95D71DF0C ``` Note that x19 is 0, so some pointer to a structure or class is nullptr here. The tests might not be behaving as they should, but given the crash is inside Windows Terminal, I don't think it should lead to all the terminal windows being closed. The test exe doesn't fail either, I didn't notice this bug because lldb tests failed, I just happened to reproduce some other failure inside a Windows Terminal and it crashed then. I think our buildbots are using conhost, which hid the issue. ``` C:\Users\tcwg>.\test.exe C:\Users\tcwg>echo %errorlevel% 0 ``` Random observations: * This does not crash conhost or other conhost instances you happen to have open. * Admin instances of Windows Terminal do not crash when the non-admin ones do.
Author
Owner

@DavidSpickett commented on GitHub (Jun 18, 2025):

This is a bit like https://github.com/microsoft/terminal/issues/18458, but without a reproducer for that one, I can't say whether it is the same thing.

@DavidSpickett commented on GitHub (Jun 18, 2025): This is a bit like https://github.com/microsoft/terminal/issues/18458, but without a reproducer for that one, I can't say whether it is the same thing.
Author
Owner

@lhecker commented on GitHub (Jun 18, 2025):

Can you try the Canary build linked in the other issue? I'm curious if it fixed this as well.

I found that my bug fix for the other issue is not 100% correct, but the current architecture makes it very difficult to fix it properly, so I'm not sure if I can do something about it. 😢

@lhecker commented on GitHub (Jun 18, 2025): Can you try [the Canary build](https://aka.ms/terminal-canary-installer) linked in the other issue? I'm curious if it fixed this as well. I found that my bug fix for the other issue is not 100% correct, but the current architecture makes it very difficult to fix it properly, so I'm not sure if I can do something about it. 😢
Author
Owner

@DavidSpickett commented on GitHub (Jun 18, 2025):

Installed that and set the canary build (1.24.1681.0) as the default terminal so the new process open in that. The issue is still present.

I checked whether the canary windows crashing would also take out a non-canary window and no, it does not (I thought it might if this was a deeper problem in Windows).

@DavidSpickett commented on GitHub (Jun 18, 2025): Installed that and set the canary build (1.24.1681.0) as the default terminal so the new process open in that. The issue is still present. I checked whether the canary windows crashing would also take out a non-canary window and no, it does not (I thought it might if this was a deeper problem in Windows).
Author
Owner

@DavidSpickett commented on GitHub (Jun 18, 2025):

Different crash point though.

Exception thrown at 0x00007FF99B7CD654 in WindowsTerminal.exe: Microsoft C++ exception: winrt::hresult_error at memory location 0x000000810ACFE6B0.
>	KernelBase.dll!00007ff99b7cd654()	Unknown
 	Microsoft.Terminal.Settings.Model.dll!00007ff94ac9f37c()	Unknown
 	Microsoft.Terminal.Settings.Model.dll!00007ff94ab34ffc()	Unknown
 	Microsoft.Terminal.Settings.Model.dll!00007ff94ab2ad54()	Unknown
 	Microsoft.Terminal.Settings.Model.dll!00007ff94ab2ceac()	Unknown
 	TerminalApp.dll!00007ff94ae8df14()	Unknown
 	TerminalApp.dll!00007ff94aef2154()	Unknown
 	TerminalApp.dll!00007ff94af00ca0()	Unknown
 	WindowsTerminal.exe!00007ff620a4b58c()	Unknown
 	WindowsTerminal.exe!00007ff620a68a30()	Unknown
 	WindowsTerminal.exe!00007ff620a6a80c()	Unknown
 	WindowsTerminal.exe!00007ff620a6b80c()	Unknown
 	WindowsTerminal.exe!00007ff620a6b028()	Unknown
 	user32.dll!00007ff99c751874()	Unknown
 	user32.dll!00007ff99c751294()	Unknown
 	user32.dll!00007ff99c762108()	Unknown
 	ntdll.dll!00007ff9a0492704()	Unknown
 	win32u.dll!00007ff99c397044()	Unknown
 	user32.dll!00007ff99c75dc88()	Unknown
 	WindowsTerminal.exe!00007ff620a69b84()	Unknown
 	WindowsTerminal.exe!00007ff620a46920()	Unknown
 	WindowsTerminal.exe!00007ff620a87434()	Unknown
 	WindowsTerminal.exe!00007ff620a874d4()	Unknown
 	kernel32.dll!00007ff99e0622d0()	Unknown
 	ntdll.dll!00007ff9a04f5b2c()	Unknown
@DavidSpickett commented on GitHub (Jun 18, 2025): Different crash point though. ``` Exception thrown at 0x00007FF99B7CD654 in WindowsTerminal.exe: Microsoft C++ exception: winrt::hresult_error at memory location 0x000000810ACFE6B0. ``` ``` > KernelBase.dll!00007ff99b7cd654() Unknown Microsoft.Terminal.Settings.Model.dll!00007ff94ac9f37c() Unknown Microsoft.Terminal.Settings.Model.dll!00007ff94ab34ffc() Unknown Microsoft.Terminal.Settings.Model.dll!00007ff94ab2ad54() Unknown Microsoft.Terminal.Settings.Model.dll!00007ff94ab2ceac() Unknown TerminalApp.dll!00007ff94ae8df14() Unknown TerminalApp.dll!00007ff94aef2154() Unknown TerminalApp.dll!00007ff94af00ca0() Unknown WindowsTerminal.exe!00007ff620a4b58c() Unknown WindowsTerminal.exe!00007ff620a68a30() Unknown WindowsTerminal.exe!00007ff620a6a80c() Unknown WindowsTerminal.exe!00007ff620a6b80c() Unknown WindowsTerminal.exe!00007ff620a6b028() Unknown user32.dll!00007ff99c751874() Unknown user32.dll!00007ff99c751294() Unknown user32.dll!00007ff99c762108() Unknown ntdll.dll!00007ff9a0492704() Unknown win32u.dll!00007ff99c397044() Unknown user32.dll!00007ff99c75dc88() Unknown WindowsTerminal.exe!00007ff620a69b84() Unknown WindowsTerminal.exe!00007ff620a46920() Unknown WindowsTerminal.exe!00007ff620a87434() Unknown WindowsTerminal.exe!00007ff620a874d4() Unknown kernel32.dll!00007ff99e0622d0() Unknown ntdll.dll!00007ff9a04f5b2c() Unknown ```
Author
Owner

@lhecker commented on GitHub (Jun 24, 2025):

The windowing refactor in 1.23 has fixed the crash, but it still creates empty windows with no content that stick around.
Because of this, I don't think we can backport this fix to 1.22.

@lhecker commented on GitHub (Jun 24, 2025): The windowing refactor in 1.23 has fixed the crash, but it still creates empty windows with no content that stick around. Because of this, I don't think we can backport this fix to 1.22.
Author
Owner

@lhecker commented on GitHub (Jun 24, 2025):

And the reason this can randomly crash is because the ConPTY handoff handling is set up before Terminal::Create is called and so the _stateMachine member is still nullptr. The situation is royally f..., unfortunately. Not sure how to hotfix this without uprooting everything.

@lhecker commented on GitHub (Jun 24, 2025): And the reason this can randomly crash is because the ConPTY handoff handling is set up _before_ `Terminal::Create` is called and so the `_stateMachine` member is still `nullptr`. The situation is royally f..., unfortunately. Not sure how to hotfix this without uprooting everything.
Author
Owner

@lhecker commented on GitHub (Jun 25, 2025):

Finished the investigation: The reason this happens is because two windows race to accept an incoming PTY connection. Since the NewConnection callback supports multiple subscribers, this can result in the two windows receiving the same connection. (= Instead of window A getting connection 1 and B getting 2, both A and B get 1 and 2 is silently dropped.) The current PTY handoff mechanism is... "not great", so this is a nice opportunity/justification to finally address this. 1


  1. Over time I realized that if the logic "flows" strictly top-down and then bottom-up, software is often good. This would've also prevented this bug: Right now, we have a "root" that handles a list of windows and their creation. During PTY handoff the root detects the handoff and creates the window. But then the actual handoff of the data and creation of tabs/panes is done in the window itself. This breaks the principle: It doesn't flow strictly top-down anymore. Instead, you can have 2 window instances race for 1 connection. If the "root" handled everything, and passed incoming connections "top-down" no races can occur. ↩︎

@lhecker commented on GitHub (Jun 25, 2025): Finished the investigation: The reason this happens is because two windows race to accept an incoming PTY connection. Since the `NewConnection` callback supports multiple subscribers, this can result in the two windows receiving the same connection. (= Instead of window A getting connection 1 and B getting 2, both A and B get 1 and 2 is silently dropped.) The current PTY handoff mechanism is... "not great", so this is a nice opportunity/justification to finally address this. [^1] [^1]: Over time I realized that if the logic "flows" strictly top-down and then bottom-up, software is often good. This would've also prevented this bug: Right now, we have a "root" that handles a list of windows and their creation. During PTY handoff the root detects the handoff and creates the window. But then the actual handoff of the data and creation of tabs/panes is done in the window itself. This breaks the principle: It doesn't flow strictly top-down anymore. Instead, you can have 2 window instances race for 1 connection. If the "root" handled everything, and passed incoming connections "top-down" no races can occur.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#23367