From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Nov 2025 13:27:57 +0000 (+0100) Subject: basic/terminal-util: operate on one fd in terminal_get_size_by_dsr() X-Git-Tag: v259-rc2~24^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=933c6900308fe321b8f7aa765df293969d81e399;p=thirdparty%2Fsystemd.git basic/terminal-util: operate on one fd in terminal_get_size_by_dsr() This moves the open call earlier, so that we do any state-changing operations if we actually managed to open the nonblocking fd. This makes the code more robust because if the fdreopen call fails, we won't make modifications to the state of the terminal. --- diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index b7de72daedc..f17352b41b8 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -2369,7 +2369,6 @@ int terminal_get_size_by_dsr( unsigned *ret_rows, unsigned *ret_columns) { - _cleanup_close_ int nonblock_input_fd = -EBADF; int r; assert(input_fd >= 0); @@ -2397,14 +2396,20 @@ int terminal_get_size_by_dsr( if (r < 0) return log_debug_errno(r, "Called with distinct input/output fds: %m"); + /* Open a 2nd input fd, in non-blocking mode, so that we won't ever hang in read() + * should someone else process the POLLIN. Do all subsequent operations on the new fd. */ + _cleanup_close_ int nonblock_input_fd = r = fd_reopen(input_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (r < 0) + return r; + struct termios old_termios; - if (tcgetattr(input_fd, &old_termios) < 0) + if (tcgetattr(nonblock_input_fd, &old_termios) < 0) return log_debug_errno(errno, "Failed to get terminal settings: %m"); struct termios new_termios = old_termios; termios_disable_echo(&new_termios); - if (tcsetattr(input_fd, TCSANOW, &new_termios) < 0) + if (tcsetattr(nonblock_input_fd, TCSANOW, &new_termios) < 0) return log_debug_errno(errno, "Failed to set new terminal settings: %m"); unsigned saved_row = 0, saved_column = 0; @@ -2417,13 +2422,6 @@ int terminal_get_size_by_dsr( if (r < 0) goto finish; - /* Open a 2nd input fd, in non-blocking mode, so that we won't ever hang in read() should someone - * else process the POLLIN. */ - - nonblock_input_fd = r = fd_reopen(input_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); - if (r < 0) - goto finish; - usec_t end = usec_add(now(CLOCK_MONOTONIC), CONSOLE_REPLY_WAIT_USEC); char buf[STRLEN("\x1B[1;1R")]; /* The shortest valid reply possible */ size_t buf_full = 0; @@ -2516,7 +2514,7 @@ finish: if (saved_row > 0 && saved_column > 0) RET_GATHER(r, terminal_set_cursor_position(output_fd, saved_row, saved_column)); - RET_GATHER(r, RET_NERRNO(tcsetattr(input_fd, TCSANOW, &old_termios))); + RET_GATHER(r, RET_NERRNO(tcsetattr(nonblock_input_fd, TCSANOW, &old_termios))); return r; }