terminal-util: don't query terminal size on virtual consoles
terminal_fix_size() queries the terminal for its dimensions with CSI 18 and DSR. On a virtual console that is pointless: the kernel renders the screen itself, so TIOCGWINSZ is already authoritative. It is also slow. PID 1 queries /dev/console from console_setup(), and writes there go through redirected_tty_write(), so while plymouth holds a TIOCCONS redirect the query never reaches the VT and no reply is ever generated. Each query then waits out CONSOLE_ANSI_SEQUENCE_TIMEOUT_USEC. Previously the write failed immediately with EAGAIN — the kernel forces O_NONBLOCK on /dev/console — so the query was abandoned at no cost; sinceba10d789a8it is retried until the timeout instead. On a Steam Deck booting with console=tty1 and plymouth the two queries cost 667ms, about a quarter of userspace boot time, and no log level shows it because main() runs console_setup() between log_close() and log_open(). So skip the query on a virtual console and keep the dimensions the kernel gave us, reporting success rather than an error: declining to ask is not a failure, and the "dimensions already match" path below returns 0 for the same reason. Note this also skips the query on a /dev/ttyN that would have answered, and does not help a serial console behind a TIOCCONS redirect. Fixes:ba10d789a8Fixes:d91a184509(cherry picked from commit4ca7ac0275)
This commit is contained in:
committed by
Luca Boccassi
parent
412876f581
commit
ffb5f4bf45
@@ -2681,17 +2681,32 @@ int terminal_get_size(
|
||||
return r;
|
||||
}
|
||||
|
||||
static int fd_is_vc(int fd) {
|
||||
_cleanup_free_ char *name = NULL;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
r = getttyname_harder(fd, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return tty_is_vc_resolve(name);
|
||||
}
|
||||
|
||||
int terminal_fix_size(int input_fd, int output_fd) {
|
||||
unsigned rows, columns;
|
||||
int r;
|
||||
|
||||
/* Tries to update the current terminal dimensions to the ones reported via ANSI sequences.
|
||||
*
|
||||
* Why bother with this? The ioctl() information is often incorrect on serial terminals (since
|
||||
* there's no handshake or protocol to determine the right dimensions in RS232), but since the ANSI
|
||||
* sequences are interpreted by the final terminal instead of an intermediary tty driver they should
|
||||
* be more accurate.
|
||||
*/
|
||||
/* Don't ask a virtual console at all. There is no intermediary here that could be wrong about the
|
||||
* dimensions: the kernel renders the screen itself, so its winsize is authoritative. */
|
||||
r = fd_is_vc(input_fd);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to determine whether terminal is a virtual console, assuming it is not: %m");
|
||||
else if (r > 0) {
|
||||
log_debug("Not querying dimensions of a virtual console, kernel dimensions are authoritative.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct winsize ws = {};
|
||||
if (ioctl(output_fd, TIOCGWINSZ, &ws) < 0)
|
||||
|
||||
Reference in New Issue
Block a user