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

Maximizing/Restoring when the alt buffer is active crashes conhost #1206

Closed
DHowett-MSFT opened this issue Jun 11, 2019 · 4 comments · Fixed by #2666
Closed

Maximizing/Restoring when the alt buffer is active crashes conhost #1206

DHowett-MSFT opened this issue Jun 11, 2019 · 4 comments · Fixed by #2666
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. Priority-1 A description (P1) Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. Severity-Crash Crashes are real bad news.
Milestone

Comments

@DHowett-MSFT
Copy link
Contributor

DHowett-MSFT commented Jun 11, 2019

  1. wsl
  2. printf '\e[?1049h'
  3. maximize
  4. did it crash? if not, restore
  5. did it crash? if not, maximize
  6. did it crash? if not, close this bug

Notably, the crash doesn't occur for simple resizes -- even those covering more than one side.

@DHowett-MSFT DHowett-MSFT added Product-Conhost For issues in the Console codebase Area-Output Related to output processing (inserting text into buffer, retrieving buffer text, etc.) Issue-Bug It either shouldn't be doing this or needs an investigation. Severity-Crash Crashes are real bad news. labels Jun 11, 2019
@DHowett-MSFT DHowett-MSFT added this to the 20H1 milestone Jun 11, 2019
@ghost ghost added the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Jun 11, 2019
@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 Jun 11, 2019
@DHowett-MSFT
Copy link
Contributor Author

 	OpenConsole.exe!wil::details::in1diag5::_Throw_Hr(void * callerReturnAddress, unsigned int lineNumber, const char * fileName, const char * functionName, const char * code, HRESULT hr) Line 4937	C++
 	OpenConsole.exe!wil::details::in1diag5::Throw_HrIf(void * callerReturnAddress, unsigned int lineNumber, const char * fileName, const char * functionName, const char * code, HRESULT hr, bool condition) Line 5041	C++
 	OpenConsole.exe!TextBufferCellIterator::TextBufferCellIterator(const TextBuffer & buffer, _COORD pos, const Microsoft::Console::Types::Viewport limits) Line 43	C++
 	OpenConsole.exe!TextBuffer::GetCellDataAt(const _COORD at, const Microsoft::Console::Types::Viewport limit) Line 169	C++
 	OpenConsole.exe!Microsoft::Console::Render::Renderer::_PaintBufferOutput(Microsoft::Console::Render::IRenderEngine * const pEngine) Line 579	C++
 	OpenConsole.exe!Microsoft::Console::Render::Renderer::_PaintFrameForEngine(Microsoft::Console::Render::IRenderEngine * const pEngine) Line 119	C++
 	OpenConsole.exe!Microsoft::Console::Render::Renderer::PaintFrame() Line 68	C++
 	OpenConsole.exe!Microsoft::Console::Render::RenderThread::_ThreadProc() Line 168	C++
 	OpenConsole.exe!Microsoft::Console::Render::RenderThread::s_ThreadProc(void * lpParameter) Line 151	C++

@DHowett-MSFT DHowett-MSFT added Area-Rendering Text rendering, emoji, complex glyph & font-fallback issues and removed Area-Output Related to output processing (inserting text into buffer, retrieving buffer text, etc.) labels Jun 11, 2019
@zadjii-msft zadjii-msft self-assigned this Aug 27, 2019
@zadjii-msft
Copy link
Member

This only repros if "Disable scroll forward" is enabled.

This surprises me, considering the alt buffer doesn't need to do anything with _virtualBottom, but something's definitely busted there.

@zadjii-msft
Copy link
Member

This code looks bad: SCREEN_INFORMATION::_InternalSetViewportSize

> OpenConsole!SCREEN_INFORMATION::_InternalSetViewportSize+0x5ca [...OpenConsole\src\host\screenInfo.cpp @ 1241] 
  OpenConsole!SCREEN_INFORMATION::_AdjustViewportSize+0x157 [...\OpenConsole\src\host\screenInfo.cpp @ 1297] 
  OpenConsole!SCREEN_INFORMATION::ProcessResizeWindow+0x14c [...\OpenConsole\src\host\screenInfo.cpp @ 887] 
  OpenConsole!Microsoft::Console::Interactivity::Win32::Window::_HandleWindowPosChanged+0x135 [...\OpenConsole\src\interactivity\win32\WindowProc.cpp @ 812] 
  OpenConsole!Microsoft::Console::Interactivity::Win32::Window::ConsoleWindowProc+0x101c [...\OpenConsole\src\interactivity\win32\WindowProc.cpp @ 478] 
    if (gci.IsTerminalScrolling() && newViewport.Height() != _viewport.Height())
    {
        const short newTop = static_cast<short>(std::max(0, _virtualBottom - (newViewport.Height() - 1)));

        newViewport = Viewport::FromDimensions(COORD({ newViewport.Left(), newTop }), newViewport.Dimensions());
    }

During the resize down, we're resizing the alt buffer here. Prior to the newViewport = Viewport::FromDimensions(... line, members have the following values:

Variable value
newTop 76
_virtualBottom 105
newViewport {LT(0, 0) RB(119, 29) [120 x 30]}
_viewport {LT(0, 0) RB(370, 105) [371 x 106]}

Looks like we're trying to set the top of the new viewport so that the virtual bottom stays anchored to the new viewport's bottom. However, this only makes sense when the viewport is getting bigger, not when it's getting smaller. In that scenario, we'll end up setting the top to somewhere in the middle of the buffer, and then be real confused by the next paint.

zadjii-msft added a commit that referenced this issue Sep 3, 2019
@ghost ghost added the In-PR This issue has a related PR label Sep 5, 2019
zadjii-msft added a commit that referenced this issue Sep 5, 2019
## Summary of the Pull Request

When a user had "Disable Scroll Forward" enabled and switched to the alt buffer and maximized the console, then restored down, we'd crash. Now we don't.

## References

## PR Checklist
* [x] Closes #1206 
* [x] I work here
* [x] Tests added/passed

## Detailed Description of the Pull Request / Additional comments

The problem is that we'd previously try to "anchor" the viewport to the virtual bottom when resizing like this. This would also cause us to move the top of the viewport down, into the buffer. However, if the alt buffer is getting smaller, we don't want to do this - if we anchor to the old _virtualBottom, the bottom of the viewport will actually be outside the current buffer.

This could theoretically happen with the main buffer too, but it's much easier to repro with the alt buffer.
@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 Sep 5, 2019
@DHowett-MSFT DHowett-MSFT added the Priority-1 A description (P1) label Sep 5, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Sep 5, 2019
DHowett-MSFT pushed a commit that referenced this issue Sep 23, 2019
## Summary of the Pull Request

When a user had "Disable Scroll Forward" enabled and switched to the alt buffer and maximized the console, then restored down, we'd crash. Now we don't.

## References

## PR Checklist
* [x] Closes #1206
* [x] I work here
* [x] Tests added/passed

## Detailed Description of the Pull Request / Additional comments

The problem is that we'd previously try to "anchor" the viewport to the virtual bottom when resizing like this. This would also cause us to move the top of the viewport down, into the buffer. However, if the alt buffer is getting smaller, we don't want to do this - if we anchor to the old _virtualBottom, the bottom of the viewport will actually be outside the current buffer.

This could theoretically happen with the main buffer too, but it's much easier to repro with the alt buffer.

(cherry picked from commit c58033c)
@ghost
Copy link

ghost commented Sep 24, 2019

🎉This issue was addressed in #2666, which has now been successfully released as Windows Terminal Preview v0.5.2661.0.:tada:

Handy links:

ghost pushed a commit that referenced this issue May 2, 2022
The "virtual bottom" marks the last line of the mutable viewport area,
which is the part of the buffer that VT sequences can write to. This
region should typically only move downwards as new lines are added to
the buffer, but there were a number of cases where it was incorrectly
being moved up, or moved down further than necessary. This PR attempts
to fix that.

There was an earlier, unsuccessful attempt to fix this in PR #9770 which
was later reverted (issue #9872 was the reason it had to be reverted).
PRs #2666, #2705, and #5317 were fixes for related virtual viewport
problems, some of which have either been extended or superseded by this
PR.

`SetConsoleCursorPositionImpl` is one of the cases that actually does
need to move the virtual viewport upwards sometimes, in particular when
the cmd shell resets the buffer with a `CLS` command. But when this
operation "snaps" the viewport to the location of the cursor, it needs
to use the virtual viewport as the frame of reference. This was
partially addressed by PR #2705, but that only applied in
terminal-scrolling mode, so I've now applied that fix regardless of the
mode.

`SetViewportOrigin` takes a flag which determines whether it will also
move the virtual bottom to match the visible viewport. In some case this
is appropriate (`SetConsoleCursorPositionImpl` being one example), but
in other cases (e.g. when panning the viewport downwards in the
`AdjustCursorPosition` function), it should only be allowed to move
downwards. We can't just not set the update flag in those cases, because
that also determines whether or not the viewport would be clamped, and
we don't want change that. So what I've done is limit
`SetViewportOrigin` to only move the virtual bottom downwards, and added
an explicit `UpdateBottom` call in those places that may also require
upward movement.

`ResizeWindow` in the `ConhostInternalGetSet` class has a similar
problem to `SetConsoleCursorPositionImpl`, in that it's updating the
viewport to account for the new size, but if that visible viewport is
scrolled back or forward, it would end up placing the virtual viewport
in the wrong place. So again the solution here was to use the virtual
viewport as the frame of reference for the position. However, if the
viewport is being shrunk, this can still result in the cursor falling
below the bottom, so we need an additional check to adjust for that.
This can't be applied in pty mode, though, because that would break the
conpty resizing operation.

`_InternalSetViewportSize` comes into play when resizing the window
manually, and again the viewport after the resize can end up truncating
the virtual bottom if not handled correctly. This was partially
addressed in the original code by clamping the new viewport above the
virtual bottom under certain conditions, and only in terminal scrolling
mode. I've replaced that with a new algorithm which links the virtual
bottom to the visible viewport bottom if the two intersect, but
otherwise leaves it unchanged. This applies regardless of the scrolling
mode.

`ResizeWithReflow` is another sizing operation that can affect the
virtual bottom. This occurs when a change of the window width requires
the buffer to be reflowed, and we need to reposition the viewport in the
newly generated buffer. Previously we were just setting the virtual
bottom to align with the new visible viewport, but that could easily
result in the buffer truncation if the visible viewport was scrolled
back at the time. We now set the virtual bottom to the last non-space
row, or the cursor row (whichever is larger). There'll be edge cases
where this is probably not ideal, but it should still work reasonably
well.

`MakeCursorVisible` was another case where the virtual bottom was being
updated (when requested with a flag) via a `SetViewportOrigin` call.
When I checked all the places it was used, though, none of them actually
required that behavior, and doing so could result in the virtual bottom
being incorrectly positioned, even after `SetViewportOrigin` was limited
to moving the virtual bottom downwards. So I've now made it so that
`MakeCursorVisible` never updates the virtual bottom.

`SelectAll` in the `Selection` class was a similar case. It was calling
`SetViewportOrigin` with the `updateBottom` flag set when that really
wasn't necessary and could result in the virtual bottom being
incorrectly set. I've changed the flag to false now.

## Validation Steps Performed

I've manually confirmed that the test cases in issue #9754 are working
now, except for the one involving margins, which is bigger problem with
`AdjustCursorPosition` which will need to be addressed separately.

I've also double checked the test cases from several other virtual
bottom issues (#1206, #1222, #5302, and #9872), and confirmed that
they're still working correctly with these changes.

And I've added a few screen buffer tests in which I've tried to cover as
many of the problematic code paths as possible.

Closes #9754
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. Priority-1 A description (P1) Product-Conhost For issues in the Console codebase Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. Severity-Crash Crashes are real bad news.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants