[hackers] [PATCH] fully flush input buffer

From: S. Gilles <sgilles_AT_math.umd.edu>
Date: Sun, 21 Apr 2019 20:34:51 -0400

---
Here's a bug report, also with a fix. To reproduce:
 - have st display something that needs a non-trivial time to refresh.
   (For my testing, I used ~70 rows, ~150 cols, displaying the output of
       #!/bin/sh
       
       for y in $(seq 1 100); do
         for x in $(seq 1 100); do
           a=$(( $(head -c 1 /dev/urandom | od -t u1 -A n | tr -d ' ') % 256 ))
           printf '\033[38;5;%dm\033[48;5;%dm#' $a $(( 255 - $a ))
         done
         printf '\033[0m\n'
       done
   with less, which displays the issue exceptionally quickly.)
 - cause a bunch of redraws (scroll up and down for a few seconds at a
   time, repeatedly)
 - after a while, your keypresses will no longer have the correct
   effect since the input buffer is clogged (pressing `j' might make a
   `k' available to less)
 - to fix this, cause a bunch of trivial X events, like highlighting
   text repeatedly
This patch addresses the issue by making a few more passes of pselect(2)
with a non-NULL timeout every time input is handled. Now, st doesn't
wait for new input in order to handle the backlog from ttyfd, it just
churns through everything its given until there is no more.
Take it, drop it, rewrite it, I don't care.
 x.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/x.c b/x.c
index 5828a3b..82cbec6 100644
--- a/x.c
+++ b/x.c
_AT_@ -1800,6 +1800,7 @@ run(void)
 	fd_set rfd;
 	int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
 	int ttyfd;
+	int cleanup = 0;
 	struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
 	long deltatime;
 
_AT_@ -1836,6 +1837,7 @@ run(void)
 			die("select failed: %s\n", strerror(errno));
 		}
 		if (FD_ISSET(ttyfd, &rfd)) {
+			cleanup = 2;
 			ttyread();
 			if (blinktimeout) {
 				blinkset = tattrset(ATTR_BLINK);
_AT_@ -1844,8 +1846,10 @@ run(void)
 			}
 		}
 
-		if (FD_ISSET(xfd, &rfd))
+		if (FD_ISSET(xfd, &rfd)) {
+			cleanup = 2;
 			xev = actionfps;
+		}
 
 		clock_gettime(CLOCK_MONOTONIC, &now);
 		drawtimeout.tv_sec = 0;
_AT_@ -1893,8 +1897,10 @@ run(void)
 					drawtimeout.tv_sec = \
 					    drawtimeout.tv_nsec / 1E9;
 					drawtimeout.tv_nsec %= (long)1E9;
-				} else {
+				} else if (!cleanup) {
 					tv = NULL;
+				} else {
+					cleanup--;
 				}
 			}
 		}
-- 
2.21.0
Received on Mon Apr 22 2019 - 02:34:51 CEST

This archive was generated by hypermail 2.3.0 : Mon Apr 22 2019 - 03:24:23 CEST