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

Terminal resize not always propagated to program running under winpty #110

Closed
rprichard opened this issue Apr 22, 2017 · 4 comments
Closed
Labels

Comments

@rprichard
Copy link
Owner

See this issue, microsoft/vscode#17609.

It can be reproduced without VSCode. On the VM I'm testing right now, it seems not to reproduce most of the time. I'm not sure what I have to to do to reliably trigger the bug. Maybe maximizing the window helps, maybe using AltDrag or a similar tool helps.

Steps:

  1. In mintty, run WSL or Cygwin bash under winpty.
  2. Make the window narrow.
  3. Make the window wide.
  4. Run this command, (cmd.exe /c mode | grep Columns) && echo $COLUMNS

The true console width will be greater than the width that bash thinks the window has:

$ (cmd.exe /c mode | grep Columns) && echo $COLUMNS
    Columns:        148
134
@rprichard
Copy link
Owner Author

When winpty makes the terminal wider, it first expands the buffer with SetConsoleScreenBufferSize, then expands the window with SetConsoleWindowInfo.

I think the WSL bash.exe wrapper sees the WINDOW_BUFFER_SIZE_EVENT event, then records the new window size and raises SIGWINCH. Every successive TIOCGWINSZ operation reads this recorded window size. (I noticed in my testing that once the console and WSL sizes are out-of-sync, TIOCGWINSZ returns the wrong size even seconds later.)

If WSL bash.exe retrieves the window size after the buffer has been expanded, but before the window has been expanded, then it will record the older, incorrect size.

Synthesizing a WINDOW_BUFFER_SIZE_EVENT after the buffer-and-window-resize operation is finished seems to fix the problem.

This theory explains the issue with WSL bash, but not Cygwin bash. When I run Cygwin bash in a console, the $LINES value updates as I resize the console window vertically. (OTOH, it's unset when I start bash, and it doesn't update when I'm running a child program.)

@CherryDT
Copy link

Is bash.exe's behavior "according to the rules"? (Are there even rules?) I.e., does this mean an issue should be opened in https://github.com/Microsoft/BashOnWindows/ too?

@rprichard
Copy link
Owner Author

I looked at Cygwin master (https://github.com/mirror/newlib-cygwin). It issues SIGWINCH from fhandler_console::send_winch_maybe. It's a mess:

  1. It's less aggressive than WSL at issuing the signal, because it will only issue the signal during certain operations. I think the idea is that the console input queue is ignored unless the Cygwin program reads from it. A WSL program, on the other hand, will receive SIGWINCH even if it ignores the stdin tty, because the WSL bash.exe bridge is always reading from the console input queue.

  2. It's more aggressive than WSL, because it isn't relying solely on WINDOW_BUFFER_SIZE_EVENT events to raise SIGWINCH. It seems to check the window size even after ordinary key events.

  3. It's less aggressive than WSL, because there seems to be a bug in fhandler_console::send_winch_maybe. It calls dev_console::fillin to update dwWinSize, and if fillin changes dwWinSize, then send_winch_maybe raises the signal. There are several other code paths that call fillin, though. If one of those paths updates dwWinSize, then send_winch_maybe won't notice the change, so the signal won't be issued. Presumably send_winch_maybe should keep track of the last size it issued a signal for, like how set_cursor_maybe records the last cursor position it used.

Here's a Cygwin/WSL test program I used: https://gist.github.com/rprichard/d1512c1fea735b8929371d82dfcb08cc.

@rprichard
Copy link
Owner Author

@CherryDT This issue on BashOnWindows is closely related, microsoft/WSL#1001. There's clearly a need for WSL bash.exe to detect when the console window's height has changed, but the Windows console doesn't provide a good way to do that. (Options include polling at an interval, polling at opportune moments, maybe registering for EVENT_CONSOLE_LAYOUT WinEvents if the console has an HWND?)

For this issue, I'm inclined to have winpty synthesize a somewhat out-of-place WINDOW_BUFFER_SIZE_EVENT after it's finished its window-and-buffer resizing work. It won't match what the console does, but it'll fix this particular resizing issue with WSL, and improve the situation with Cygwin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants