Detectng missed SIGWINCH in Bash extension, when apparent terminal size has not changed
2
votes
1
answer
74
views
I maintain an extension for the Bash environment called [Basta](https://www.kylheku.com/cgit/basta/about) . Basta provides a scroll-protected status line at the bottom of your ANSI/VT100 terminal.
When Basta sets itself up, the effective number of lines, as known by the termios stuff in the kernel and the shell
LINES
variable decreases by 1. Resizing the terminal is handled nicely. Almost. There is trap
for the SIGWINCH
signal to call the update routine, which is also called after every command, prior to returning to the prompt.
However, from time to time I see a situation in which the scrolling region is lost. The prompt is being painted over the bottom line, where the user is editing commands and where command output appears, resulting in a mess.
I have a hypothesis on one how it can occur, which has reliable repro steps.
1. We run a program that waits for input, while Bash is in the background, such as cat
.
2. While this program is running, we resize the window such that we shrink it by one line.
3. Terminate the cat
program.
If the terminal is resized while cat
is running, Bash does not get the SIGWINCH
(because, I think, SIGWINCH
is only sent to the processes in the terminal sessions foreground process group, and Bash is in the Background at that moment). Our trap
does not execute.
Basta's update function also relies on comparing the previous terminal size to the current to detect a size change.
**Here is the problem:** in this situation where a terminal with a scroll-protected status like has shrunk by one line, the **number of lines appears not to have changed**.
E.g. 40 line screen with 39 line scrolling region: LINES=39
. Resize terminal to be 39 lines long. Scrolling region is gone. LINES=39
again. To the software, it looks like the same size, so it concludes that there has not been a resize. The status line is now being painted over top of the bottom row, over top of the user's input, because Basta wants to put it on row 40, which doesn't exist any more, so the cursor clamps to 39.
If Basta knows what a window size change occurred, it will not do the size comparison; in that situation it takes the slow path whereby it queries the terminal itself to determine the size. (It would be undesirable to do that for each update, because sending queries to the terminal is dodgy. If the user is typing rapidly, the terminal response can get mixed up with their keystrokes, and there can be a noticeable delay in getting a response from the terminal over laggy remote connections.)
Is there any clever way to know that the terminal has changed (or at least suspect it with a reasonably low false positive rate), in the absence of having received the WINCH
trap, due to having been in the background, without talking to the terminal?
Asked by Kaz
(8867 rep)
Feb 7, 2025, 07:54 PM
Last activity: Feb 11, 2025, 02:04 AM
Last activity: Feb 11, 2025, 02:04 AM