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

Bug Report: What is reordering VT escape sequences in my string? #2011

Closed
jazzdelightsme opened this issue Jul 17, 2019 · 4 comments · Fixed by #4896
Closed

Bug Report: What is reordering VT escape sequences in my string? #2011

jazzdelightsme opened this issue Jul 17, 2019 · 4 comments · Fixed by #4896
Assignees
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Tag-Fix Doesn't match tag requirements Priority-1 A description (P1) Product-Conpty For console issues specifically related to conpty Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Milestone

Comments

@jazzdelightsme
Copy link
Member

Environment

Windows build number: Microsoft Windows [Version 10.0.18362.239]
Windows Terminal version (if applicable): (built from latest source as of July 17th, 2019, morning)

I am working on implementing some new VT escape sequences (PR here), but I've run into a strange problem. What the sequences do (or are supposed to do) is not important here. The problem is that in certain circumstances, something is reordering VT escape sequences in my content (which is very surprising to me).

The control sequences in question are XTPUSHSGR and XTPOPSGR: [CSI]#p and [CSI]#q, respectively. Note in the string below, how there is an XTPUSHSGR sequence, then a normal SGR sequence to set the color to red, then an XTPOPSGR sequence (and then a normal SGR sequence to reset the color).

When I open OpenConsole.sln in Visual Studio 2019, with the CascadiaPackage set as the default project to debug, and then F5 to start debugging it, it launches a terminal running Windows PowerShell. When I send my string to the console, something is moving the XTPUSHSGR and XTPOPSGR sequences to the very beginning of the string!

Steps to reproduce

  1. Start OpenConsole.sln in Visual Studio 2019. Make sure CascadiaPackage is the default project, and platform is set to x64, and build the solution if necessary.
  2. F5 to start debugging a new instance. You should now have a PowerShell instance in the terminal.
  3. In the PowerShell instance in the terminal, run the following commands:
 $esc = [char] 0x1b
 $s = "Hello. Push:${esc}[#p ${esc}[91m this text is RED Pop:${esc}[#q FG should " +
      "no longer be red (unless it was red before) courtesy reset: ${esc}[0m"
  1. Set a breakpoint at TerminalControl.dll!Microsoft::Console::VirtualTerminal::StateMachine::ProcessString (the two-parameter one).
  2. In the PowerShell instance in the terminal, run the command $s to output the string.
  3. When you hit the breakpoint, observe the value of rgwch.

Expected behavior

The content of the string should be just as it was set in PowerShell.

Actual behavior

The XTPUSHSGR and XTPOPSGR sequences have been moved to the beginning of the string!

My first thought was that PowerShell must be doing something funny, but I attached windbg to the PowerShell and set a breakpoint on kernel32!WriteConsoleW, and the string passed in there is correct. So something is happening after the string has left PowerShell's hands.

@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Jul 17, 2019
@zadjii-msft
Copy link
Member

I'm willing to bet serious money that when conhost in conpty mode processes a long string with VT sequences in it that conhost doesn't understand, we render the failing VT sequences before we repaint for the rest of the string.

So for your example string: "Hello. Push:${esc}[#p ${esc}[91m this text is RED Pop:${esc}[#q FG should no longer be red (unless it was red before) courtesy reset: ${esc}[0m"

Conhost is going to try and process that entire string in one frame. Conpty is only going to render the output at the end of a frame, once every 60th of a second. However, as soon as the adapter (adaptDispatch) sees a sequence it doesn't understand, it will dispatch it to the terminal immediately. So the push/pops will appear in the stream before the rest of the frame is rendered.

Possible solutions:

  • A workaround might just be to split the push/pops into separate strings to write to the terminal. It might trigger a frame in between them and the actual text, and it'll appear correctly.
$push = "${esc}[#p"
$red = "${esc}[91m"
$pop = "${esc}[#q"
$reset = "${esc}[0m"
$s1 = "Hello. Push:"
$s2 = "this text is RED Pop:${esc}[#q FG should no longer be red (unless it was red before) courtesy reset: ${esc}[0m"
$s3 = "FG should no longer be red (unless it was red before) courtesy reset: "
  • A more correct solution would be to have conpty actually be able to process those sequences, though this issue will remain for any sequences conhost doesn't understand
  • Maybe the most correct solution would be to have conpty force a frame when it encounters a sequence it doesn't recognize. That might really hit perf though, so I'd be cautious with that change.

@zadjii-msft zadjii-msft added Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conpty For console issues specifically related to conpty labels Jul 17, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Jul 17, 2019
@zadjii-msft zadjii-msft added this to the 20H1 milestone Jul 17, 2019
@jazzdelightsme
Copy link
Member Author

Whoa. Interesting. Thanks for the explanation, @zadjii-msft ; I would never have figured that out.

Part of my problem seems to be a debugging problem: in my branch with some code changes to handle those sequences, I implemented the push/pop commands in the Terminal class, but in the adaptDispatch stuff, I just returned false. I had set breakpoints in the adaptDispatch functions... but when debugging the CascadiaPackage, those breakpoints are disabled, claiming that no symbols have been loaded for the document, so I thought that code was not even running.

But the code definitely IS running... if I change the adaptDispatch layer to just return true (without actually doing anything), the behavior changes!

Although I don't understand the changed behavior... now the push/pop control sequences are simply gone. Should the adaptDispatch layer be doing something to send the sequences on down the line?

@zadjii-msft
Copy link
Member

Oh that's because debugging the Terminal's conhost is a pain. Basically, Windows Terminal is running attached to another conhost process, and that conhost process is where adaptDispatch is running. To be able to debug it with VS, you need to manually attach VS to the child conhost process that the Terminal started.

@DHowett-MSFT DHowett-MSFT removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Jul 20, 2019
@DHowett-MSFT
Copy link
Contributor

Marking this one triaged; it's definitely something we should look at, but we may not have the bandwidth to do so.

@zadjii-msft zadjii-msft self-assigned this Aug 27, 2019
@ghost ghost added the In-PR This issue has a related PR label Sep 5, 2019
@DHowett-MSFT DHowett-MSFT added the Priority-1 A description (P1) label Sep 5, 2019
@cinnamon-msft cinnamon-msft modified the milestones: 20H1, 21H1 Nov 14, 2019
zadjii-msft added a commit that referenced this issue Mar 12, 2020
…h the frame

    ## Summary of the Pull Request

    When Conpty encounters a string we don't understand, immediately flush the frame.

    ## References

    This PR superceeds #2665. This solution is much simpler than what was proposed in that PR.
    As mentioned in #2665: "This might have some long-term consequences for #1173."

    ## PR Checklist
    * [x] Closes #2011
    * [x] Closes #4106
    * [x] I work here
    * [x] Tests added/passed
    * [n/a] Requires documentation to be updated
DHowett-MSFT pushed a commit that referenced this issue Mar 12, 2020
When ConPTY encounters a string we don't understand, immediately flush the frame.

## References

This PR supersedes #2665. This solution is much simpler than what was proposed in that PR. 
As mentioned in #2665: "This might have some long-term consequences for #1173."

## PR Checklist
* [x] Closes #2011
* [x] Closes #4106
* [x] I work here
* [x] Tests added/passed
@ghost ghost added Needs-Tag-Fix Doesn't match tag requirements Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Mar 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Tag-Fix Doesn't match tag requirements Priority-1 A description (P1) Product-Conpty For console issues specifically related to conpty Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
4 participants