]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/terminal-util: operate on one fd in terminal_get_size_by_dsr()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 20 Nov 2025 13:27:57 +0000 (14:27 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 20 Nov 2025 15:54:43 +0000 (16:54 +0100)
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.

src/basic/terminal-util.c

index b7de72daedc67d08ef6d78f308ec73191522d7e1..f17352b41b8a85bcdcac5968a4ce298cf3b77214 100644 (file)
@@ -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;
 }