[megathread] ConPTY buffer gets out-of-sync #20488

Open
opened 2026-01-31 07:15:16 +00:00 by claunia · 5 comments
Owner

Originally created by @tusharsnx on GitHub (Sep 17, 2023).

Originally assigned to: @lhecker on GitHub.

maintainer edit: we're promoting this to a megathread cause this is a Hard problem. This is now tracking "try to make an in-proc version of conpty"

See: https://github.com/microsoft/terminal/issues/15976#issuecomment-1722596700 for details.

Thoughts:

  • fix the conhost singletons?
  • Load conhost.exe as a dll
  • Keep the pipes (but in proc!)

Things we might be able to actually solve with this:


Windows Terminal version

1.17.11461.0

Windows build number

22621.2283

Other Software

No response

Steps to reproduce

This is an indirect repro, since we can't see how the openconsole buffer looks like at any instant when it's acting as a conpty.

  • Open wt.exe and openconsole.exe.
  • Go to open console's Layout settings, and set "Screen Buffer Size" height to 1 (for now, this removes the scrollback region and makes this openconsole behave like conpty.)
  • Pick a string that can easily wrap several times if we shrink the window size for both WT and OpenConsole, example:
"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80"
  • Put the string into the prompt and try to find an optimal window size where both the WT and openconsole has exactly the same amount of rows and cols on the screen. Avoid having scrollbars on OpenConsole while doing this, scrollbars means scrollback height is not 0 anymore, which is important for this repro. I used 12(r) x 35(c).
  • Fill the buffer with the above text. If you're using pwsh, you can simply press enter, and it will echo the string back. That should be enough in this case.
  • Now, increase the width of the window for both WT and openconsole one by one, by 1 level. This should cause a "reflow" as we call it.
  • After the reflow, WT and openconsole is out of sync on the first line of the viewport.

Expected Behavior

After the reflow, both buffers should stay in sync.

Actual Behavior

Buffers are out of sync.

Originally created by @tusharsnx on GitHub (Sep 17, 2023). Originally assigned to: @lhecker on GitHub. _maintainer edit_: we're promoting this to a megathread cause this is a **H**ard problem. This is now tracking "try to make an in-proc version of conpty" See: https://github.com/microsoft/terminal/issues/15976#issuecomment-1722596700 for details. Thoughts: * [ ] fix the conhost singletons? * [ ] Load conhost.exe as a dll * [ ] Keep the pipes (but in proc!) Things we might be able to actually solve with this: * #7449 ---- ### Windows Terminal version 1.17.11461.0 ### Windows build number 22621.2283 ### Other Software _No response_ ### Steps to reproduce This is an indirect repro, since we can't see how the openconsole buffer looks like at any instant when it's acting as a conpty. - Open `wt.exe` and `openconsole.exe`. - Go to open console's **Layout** settings, and set **"Screen Buffer Size"** height to 1 (for now, this removes the scrollback region and makes *this* openconsole behave like conpty.) - Pick a string that can easily *wrap* several times if we shrink the window size for both WT and OpenConsole, example: ```txt "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80" ``` - Put the string into the prompt and try to find an optimal window size where both the WT and openconsole has exactly the same amount of rows and cols on the screen. **Avoid having scrollbars on OpenConsole while doing this, scrollbars means *scrollback* height is not 0 anymore, which is important for this repro**. I used 12(r) x 35(c). - Fill the buffer with the above text. If you're using `pwsh`, you can simply press `enter`, and it will echo the string back. That should be enough in this case. - Now, increase the width of the window for both WT and openconsole one by one, by 1 level. This should cause a "reflow" as we call it. - After the reflow, WT and openconsole is out of sync on the first line of the viewport. ### Expected Behavior After the reflow, both buffers should stay in sync. ### Actual Behavior Buffers are out of sync.
claunia added the Needs-Tag-FixProduct-ConptyIssue-Scenario labels 2026-01-31 07:15:16 +00:00
Author
Owner

@tusharsnx commented on GitHub (Sep 17, 2023):

(If the gif doesn't fit on the screen, open it in a new tab. Will take care of it next time 😅)

demo

@tusharsnx commented on GitHub (Sep 17, 2023): (If the gif doesn't fit on the screen, open it in a new tab. Will take care of it next time 😅) ![demo](https://github.com/microsoft/terminal/assets/55626797/a6c05bbe-8f77-456f-9314-7eb967200506)
Author
Owner

@tusharsnx commented on GitHub (Sep 17, 2023):

As one can see, the problem is scrollback region. Since openconsole do not have any idea of what's in the scrollback region, it doesn't reflow like WT does. On WT, during a reflow, some of the text on the first line went back into the scrollback region, because the screen is now wider, and has some room left for more characters in the previous line (inside scrollback). OpenConsole, unaware of the scrollback, simply reflow the text as if the first character (of the viewport) is the also the first character of the whole text buffer.

To me, it seems like this is the root cause of #6546.

In the above demo, notice how the cursor is at exactly the same place on both WT and openconsole, even after the out of sync buffers (this is just because rows haven't changed their location, even though the characters within the rows did). This might be why the issue is not so obvious right when it gets out of sync. Instead, it becomes visible only after certain amount of resize and reflow, where WT buffer rows move (up/down) at different rate then the pty buffer rows.

@tusharsnx commented on GitHub (Sep 17, 2023): As one can see, the problem is `scrollback` region. Since openconsole **do not** have any idea of what's in the scrollback region, it doesn't reflow like WT does. On WT, during a reflow, some of the text on the first line went back *into the scrollback region*, because the screen is now wider, and has some room left for more characters in the previous line (inside scrollback). OpenConsole, *unaware of the scrollback*, simply reflow the text as if the first character (of the viewport) is the also the first character of the whole text buffer. To me, it seems like this is the root cause of #6546. In the above demo, notice how the cursor is at exactly the same place on both WT and openconsole, even after the out of sync buffers (this is just because rows haven't changed their location, even though the characters within the rows did). This might be why the issue is not so obvious right when it gets out of sync. Instead, it becomes visible only after certain amount of resize and reflow, where WT buffer rows move (up/down) at different rate then the pty buffer rows.
Author
Owner

@tusharsnx commented on GitHub (Sep 17, 2023):

Caught in action!

https://github.com/microsoft/terminal/assets/55626797/f1b0cc8e-66da-45af-87a8-0edf299688e8

@tusharsnx commented on GitHub (Sep 17, 2023): Caught in action! https://github.com/microsoft/terminal/assets/55626797/f1b0cc8e-66da-45af-87a8-0edf299688e8
Author
Owner

@tusharsnx commented on GitHub (Sep 17, 2023):

Just realized @zadjii-msft already have explained this in his now-closed PR https://github.com/microsoft/terminal/pull/4354#issuecomment-578967863.

@tusharsnx commented on GitHub (Sep 17, 2023): Just realized @zadjii-msft already have explained this in his now-closed PR https://github.com/microsoft/terminal/pull/4354#issuecomment-578967863.
Author
Owner

@lhecker commented on GitHub (Sep 18, 2023):

This is an indirect repro, since we can't see how the openconsole buffer looks like at any instant when it's acting as a conpty.

FYI I recently added ConsoleMonitor to this repo. You can find it in the Tools directory in VS. If you run it under Windows Terminal, you can interactively observe the contents of the ConPTY buffer.


This is a well known issue and will likely remain unresolved for now. I think we can keep this one open, but I also feel like we might want to make it into a "meta" issue that is about the architectural problem in general (= maintaining 2 buffers out of proc results in desync) and then just lists all the fallout issues it creates (like the line wrapping issue you described).

Personally speaking, I don't know how to solve it. I'm not even sure it's possible to solve it at all while maintaining ConPTY as is. Because on top of the line wrapping issue you mentioned, there's also a race condition between ConPTY reflowing its buffer and a ConPTY client like WT reflowing its buffer. Since those two can happen out of order, text or commands may be ingested by ConPTY while one buffer has been resized and the other hasn't.
One approach to improve that is to send a resize message to ConPTY, not resize the WT window, and wait for ConPTY to respond with a resize VT sequence in its output pipe. Only then we'd resize the WT window.

This however doesn't solve the issue you mentioned which requires that the ConPTY client / WT resizes its window first, so that we can send ConPTY the expected viewport contents (which only we can know since we have the scrollback), which inadvertently results in the issue I mentioned.
We could certainly conceive some mechanism to solve this. We could hold a mutex object across process boundaries, but that's too error prone. We could conceive some complex CRDT based approach, but that's questionable for a terminal and fairly complex. We could send the viewport contents from the ConPTY client to the server on resize, but that requires opt-in, the ability for the ConPTY user to serialize their buffer into VT, and more...
I have written more about my thoughts about and a long-term proposal for this here: https://github.com/microsoft/terminal/pull/15630#issuecomment-1616638425 (In particular see the section starting at "And the desync issues of course").

@lhecker commented on GitHub (Sep 18, 2023): > This is an indirect repro, since we can't see how the openconsole buffer looks like at any instant when it's acting as a conpty. FYI I recently added `ConsoleMonitor` to this repo. You can find it in the Tools directory in VS. If you run it under Windows Terminal, you can interactively observe the contents of the ConPTY buffer. --- This is a well known issue and will likely remain unresolved for now. I think we can keep this one open, but I also feel like we might want to make it into a "meta" issue that is about the architectural problem in general (= maintaining 2 buffers out of proc results in desync) and then just lists all the fallout issues it creates (like the line wrapping issue you described). Personally speaking, I don't know how to solve it. I'm not even sure it's possible to solve it at all while maintaining ConPTY as is. Because on top of the line wrapping issue you mentioned, there's also a race condition between ConPTY reflowing its buffer and a ConPTY client like WT reflowing its buffer. Since those two can happen out of order, text or commands may be ingested by ConPTY while one buffer has been resized and the other hasn't. One approach to improve that is to send a resize message to ConPTY, not resize the WT window, and wait for ConPTY to respond with a resize VT sequence in its output pipe. Only then we'd resize the WT window. This however doesn't solve the issue you mentioned which requires that the ConPTY client / WT resizes its window first, so that we can send ConPTY the expected viewport contents (which only we can know since we have the scrollback), which inadvertently results in the issue I mentioned. We could certainly conceive some mechanism to solve this. We could hold a mutex object across process boundaries, but that's too error prone. We could conceive some complex CRDT based approach, but that's questionable for a terminal and fairly complex. We could send the viewport contents from the ConPTY client to the server on resize, but that requires opt-in, the ability for the ConPTY user to serialize their buffer into VT, and more... I have written more about my thoughts about and a long-term proposal for this here: https://github.com/microsoft/terminal/pull/15630#issuecomment-1616638425 (In particular see the section starting at "And the desync issues of course").
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#20488