Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
3 tasks
tusharsnx opened this issue Sep 17, 2023 · 5 comments
Open
3 tasks

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

tusharsnx opened this issue Sep 17, 2023 · 5 comments
Assignees
Labels
Issue-Scenario Needs-Tag-Fix Doesn't match tag requirements Product-Conpty For console issues specifically related to conpty
Milestone

Comments

@tusharsnx
Copy link
Contributor

tusharsnx commented Sep 17, 2023

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: #15976 (comment) 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.

@tusharsnx tusharsnx added Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Sep 17, 2023
@tusharsnx
Copy link
Contributor Author

tusharsnx commented 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
Copy link
Contributor Author

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
Copy link
Contributor Author

tusharsnx commented Sep 17, 2023

Caught in action!

caught-in-action.mp4

@tusharsnx
Copy link
Contributor Author

Just realized @zadjii-msft already have explained this in his now-closed PR #4354 (comment).

@lhecker
Copy link
Member

lhecker commented Sep 17, 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: #15630 (comment) (In particular see the section starting at "And the desync issues of course").

@zadjii-msft zadjii-msft changed the title ConPTY buffer gets out-of-sync from the client buffer during a resize [megathread] ConPTY buffer gets out-of-sync Sep 20, 2023
@zadjii-msft zadjii-msft added this to the Backlog milestone Sep 20, 2023
@carlos-zamora carlos-zamora added Product-Conpty For console issues specifically related to conpty Issue-Scenario and removed Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Sep 20, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Tag-Fix Doesn't match tag requirements label Sep 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Scenario Needs-Tag-Fix Doesn't match tag requirements Product-Conpty For console issues specifically related to conpty
Projects
None yet
Development

No branches or pull requests

4 participants