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

Immediately flush a frame when we encounter a string we don't understand #2665

Closed

Conversation

zadjii-msft
Copy link
Member

Summary of the Pull Request

Whenever conpty encounters a VT sequence it doesn't understand, we'll make sure to flush the current frame before writing that string through to the connected terminal application.

References

This might have some long-term consequences for #1173. IIRC I wrote some code that was fairly similar for passthrough mode. This might be a subset of that code.

PR Checklist

Detailed Description of the Pull Request / Additional comments

We need to do this because some VT sequences might be dependent upon state that's currently buffered in the frame. So we'll flush the frame so the terminal also has that state, then we'll write the sequence we didn't understand/wanted to passthrough.

Validation Steps Performed

While testing this might be a bit trickier, I wrote a test script that changes the cursor color, in the middle of a big block of text. Changing the cursor color is a VT sequence we passthrough always. Before the change, the cursor color sequence would always appear before any of the related text. After the change, the text before the color sequence is always emitted before the sequence, and the text after the sequence is always emitted after.

  The solution here is to have the parser call up to the host to have the host
  paint a frame, before the parser writes the string to the terminal. This way,
  any state from the text before the string we didn't understand will be sent to
  the terminal before the string we didn't understand, which should hopefully
  maintain state like this.

  Unsure if this works with a sequence we didn't understand that's at the end of
  a frame all by itself, something that doesn't trigger another frame.

  This is hard to test unfortunately.
@zadjii-msft zadjii-msft modified the milestone: 20H1 Sep 5, 2019
@zadjii-msft zadjii-msft added Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conhost For issues in the Console codebase labels Sep 5, 2019
@DHowett-MSFT
Copy link
Contributor

Is there a risk that this will insert a full redraw (like, redraw everything for some reason) before an unknown sequence? or, after one?

Additionally, I'm concerned that a consumer of this will see the right behavior at first (texttext[unknownsequence]texttext) and then weird behavior afterwards (texttexttexttext without the [unknown sequence]) during subsequent full repaints (like powershell tends to cause, or turning on/off the alt buffer)

Do we know how much this will impact perf? How often do we even hit unknown sequences?

@zadjii-msft
Copy link
Member Author

@DHowett-MSFT

  1. I don't believe this will introduce a full repaint before the unknown sequence. All we're telling the renderer to do is to the frame it has prepared, now. It'll still only paint the region it invalidated. After the frame is done, the render engines will still get an EndPaint call the same as always, and reset their own state, so the renderer will be prepared for a fresh frame after the unknown sequence.
  2. That's definitely still a problem with this method. I don't know if there's a way for us to really solve that either, without a larger refactoring of storing the strings we didn't understand at the location we didn't understand them, then re-rendering those when the adjacent text is repainted. That's certainly not something that's a bug level fix.
  3. I don't particularly know. I don't believe we have any research on that.

@DHowett-MSFT
Copy link
Contributor

I ACK your comment but have no actionable response. Thanks!

@zadjii-msft
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Contributor

@DHowett-MSFT DHowett-MSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've become more comfortable with this over time.

// - TRUE always.
BOOL ConhostInternalGetSet::PrivatePassThroughString(const wchar_t* const rgwch, const size_t cch) const noexcept
{
// return SUCCEEDED(DoSrvPrivatePassThroughString(rgwch, cch));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a comment

}
else
{
engine.SetTerminalConnection(nullptr,
nullptr);
engine.EnableFlushing(nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems less like enabling flushing and more like not enabling flushing

@@ -2521,13 +2521,11 @@ void SCREEN_INFORMATION::SetTerminalConnection(_In_ ITerminalOutputConnection* c
OutputStateMachineEngine& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
if (pTtyConnection)
{
engine.SetTerminalConnection(pTtyConnection,
std::bind(&StateMachine::FlushToTerminal, _stateMachine.get()));
engine.EnableFlushing(std::bind(&StateMachine::FlushToTerminal, _stateMachine.get()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should file low-prio followup work to clear up the ownership here: the state machine engine shouldn't need a function bound into it from the state machine itself, especially not by an unrelated class.

zadjii-msft added a commit that referenced this pull request 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
@zadjii-msft
Copy link
Member Author

This PR was a far too complicated solution to this bug. I've got a better solution in #4896

DHowett-MSFT pushed a commit that referenced this pull request 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conhost For issues in the Console codebase
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug Report: What is reordering VT escape sequences in my string?
2 participants