Bug 427577 - Ctrl+Shift+K (Clear Scrollback and Reset) causes TTY to report incorrect size
Summary: Ctrl+Shift+K (Clear Scrollback and Reset) causes TTY to report incorrect size
Status: REPORTED
Alias: None
Product: konsole
Classification: Applications
Component: emulation (show other bugs)
Version: 19.12.3
Platform: Ubuntu Linux
: NOR normal
Target Milestone: ---
Assignee: Konsole Developer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-10-12 08:52 UTC by Roman Perepelitsa
Modified: 2020-11-09 23:30 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roman Perepelitsa 2020-10-12 08:52:58 UTC
SUMMARY

Ctrl+Shift+K (Clear Scrollback and Reset) erroneously sends SIGWINCH to the shell notifying it that the terminal window has been resized. More specifically, that the number of columns has been increased by 1.


STEPS TO REPRODUCE

1. Create file `/tmp/testwinch.c` with the following content:

    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ioctl.h>
    #include <unistd.h>

    #define CHECK(...)        \
      if ((__VA_ARGS__)) {    \
      } else {                \
        perror(#__VA_ARGS__); \
        exit(1);              \
      }

    static void print_tty_size(const char* when) {
      struct winsize w;
      CHECK(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1);
      CHECK(printf("%s: %dx%d\n", when, w.ws_row, w.ws_col) >= 0);
    }

    int main(void) {
      sigset_t sigset;
      siginfo_t siginfo;

      CHECK(sigemptyset(&sigset) == 0);
      CHECK(sigaddset(&sigset, SIGWINCH) == 0);
      CHECK(sigprocmask(SIG_BLOCK, &sigset, NULL) == 0);

      print_tty_size("Initial");
      CHECK(sigwaitinfo(&sigset, &siginfo) == SIGWINCH);
      print_tty_size("After WINCH");

      while (1) sleep(1);
    }

2. Run the following command:

    gcc -o /tmp/testwinch /tmp/testwinch.c

3. Start Konsole.

4. Open Settings > Configure Keyboard Shortcuts, set Shortcut for Clear Scrollback and Reset to Ctrl+Shift+K (this is the default) and click OK.

5. Open Settings > Edit Current Profile, set Command to /tmp/testwinch and click OK.

6. Click File > New Tab and observe the following output:

7. Press Ctrl+Shift+K.

OBSERVED RESULT

The content of the terminal window after performing step 6:

    Initial: 24x80

The content of the terminal window after performing step 7:

    After WINCH: 24x81

Note the difference in dimensions (81 vs 80 columns).

EXPECTED RESULT

The content of the terminal window after performing step 6:

    Initial: 24x80

The content of the terminal window after performing step 7:

    After WINCH: 24x80

Note that the dimension stays the same (24x80 columns).

SOFTWARE/OS VERSIONS
OS: Ubuntu 20.04.1 LTS
KDE Frameworks Version: 5.68.0
Qt Version: 5.12.8 (built against 5.12.8)

ADDITIONAL INFORMATION

The same issue can be reproduced by using zsh instead of a custom program.

1. Start Konsole.

2. Open Settings > Configure Keyboard Shortcuts, set Shortcut for Clear Scrollback and Reset to Ctrl+Shift+K (this is the default) and click OK.

3. Run the following command:

    RPS1='$(typeset -p COLUMNS >&2)' zsh -f --promptsubst

4. Press Ctrl+Shift+K.

Actual output:

    hostname% typeset -i10 COLUMNS=81
    hostname% typeset -i10 COLUMNS=80

Expected output:

    hostname% typeset -i10 COLUMNS=80
    hostname% typeset -i10 COLUMNS=80
Comment 1 Roman Perepelitsa 2020-10-12 09:06:02 UTC
For the record, I've bumped into this bug while debugging https://github.com/romkatv/powerlevel10k/issues/1051#issuecomment-706986771.
Comment 2 Ahmad Samir 2020-10-12 10:29:57 UTC
This is intentional, i.e. the tty window size is slightly increased then reverted to the original size, to workaround an issue where if you use "clear scrollback and reset" the shell prompt isn't redrawn. See:
https://commits.kde.org/konsole/d346a2ccad3950dad5ec137edce27e2930d536d6

to see the issue (with both bash and zsh):
- with xterm, press and hold Ctrl then middle click and select "Reset and clear saved lines" from the menu
- with gnome-terminal -> Terminal -> "Reset and clear"

so yes, it is a hack (a brilliant one, if I may say so), and it's still needed AFAICS.
Comment 3 Roman Perepelitsa 2020-10-12 10:43:24 UTC
Thanks for the context.

This hack causes issues when the content of prompt depends on the terminal dimensions. Here's an example:

    PROMPT=$'${(pl.$((COLUMNS))..-.)}\n> ' zsh -f --promptsubst

If you run this command in Konsole and press Ctrl+Shift+K, you'll see a duplicate line at the top.

This problem would be avoided if Ctr+Shift+K cleared scrollback and sent `^L` to the shell. This solution would rely on the shell being able to redraw its prompt upon receiving `^L`, which is not guaranteed in general. On the other hand, it's also not guaranteed that the shell redraws its prompt upon receiving SIGWINCH.

FWIW, Clear Scrollback and Reset can be implemented in Zsh in terminal-agnostic manner.

    function clear-screen-and-scrollback() { printf '\e[3J' >$TTY && zle clear-screen }
    zle -N clear-screen-and-scrollback
    # Ctrl+Alt+k -- Clear Scrollback and Reset.
    bindkey '^[^k' clear-screen-and-scrollback
Comment 4 Justin Zobel 2020-10-29 07:03:53 UTC
(In reply to Roman Perepelitsa from comment #3)
> Thanks for the context.
> 
> This hack causes issues when the content of prompt depends on the terminal
> dimensions. Here's an example:
> 
>     PROMPT=$'${(pl.$((COLUMNS))..-.)}\n> ' zsh -f --promptsubst
> 
> If you run this command in Konsole and press Ctrl+Shift+K, you'll see a
> duplicate line at the top.
> 
> This problem would be avoided if Ctr+Shift+K cleared scrollback and sent
> `^L` to the shell. This solution would rely on the shell being able to
> redraw its prompt upon receiving `^L`, which is not guaranteed in general.
> On the other hand, it's also not guaranteed that the shell redraws its
> prompt upon receiving SIGWINCH.
> 
> FWIW, Clear Scrollback and Reset can be implemented in Zsh in
> terminal-agnostic manner.
> 
>     function clear-screen-and-scrollback() { printf '\e[3J' >$TTY && zle
> clear-screen }
>     zle -N clear-screen-and-scrollback
>     # Ctrl+Alt+k -- Clear Scrollback and Reset.
>     bindkey '^[^k' clear-screen-and-scrollback

Roman would you be interested in supplying a patch to make the hack cleaner and work in all scenarios?
Comment 5 Roman Perepelitsa 2020-10-29 07:08:51 UTC
Sorry, I'm already over-committed on other projects.
Comment 6 Christoph Feck 2020-11-09 23:30:30 UTC
Thanks for the update; changing status. Feel free to set the status to ASSIGNED once you have time to submit changes to our repositories. For more information, please see https://community.kde.org/Get_Involved/development#Submit_a_Merge_Request