]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/terminal-util: operate on one fd in get_default_background_color()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 20 Nov 2025 13:33:26 +0000 (14:33 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 24 Nov 2025 20:47:57 +0000 (21:47 +0100)
This moves the open call earlier, so that we do any state-changing operations
if we actually managed to open the nonblocking fd. The code is easier to follow
this way and might be more robust.

Suprisingly, this fixes https://github.com/systemd/systemd/issues/39055: it
seems that run0 chowns /dev/stdin (in my case /dev/pts/0) to root:root, and the
second run0 can read and write stdin/stdout throught the already-open fds,
but fd_reopen fails.

Fixes https://github.com/systemd/systemd/issues/39055.

src/basic/terminal-util.c

index f17352b41b8a85bcdcac5968a4ce298cf3b77214..337c35a19346dff0e0409819545a980828a332c4 100644 (file)
@@ -2260,7 +2260,6 @@ static int scan_background_color_response(
 }
 
 int get_default_background_color(double *ret_red, double *ret_green, double *ret_blue) {
-        _cleanup_close_ int nonblock_input_fd = -EBADF;
         int r;
 
         assert(ret_red);
@@ -2280,27 +2279,26 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
                 return 0;
         }
 
+        /* 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(STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+        if (r < 0)
+                return r;
+
         struct termios old_termios;
-        if (tcgetattr(STDIN_FILENO, &old_termios) < 0)
+        if (tcgetattr(nonblock_input_fd, &old_termios) < 0)
                 return -errno;
 
         struct termios new_termios = old_termios;
         termios_disable_echo(&new_termios);
 
-        if (tcsetattr(STDIN_FILENO, TCSANOW, &new_termios) < 0)
+        if (tcsetattr(nonblock_input_fd, TCSANOW, &new_termios) < 0)
                 return -errno;
 
         r = loop_write(STDOUT_FILENO, ANSI_OSC "11;?" ANSI_ST, SIZE_MAX);
         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(STDIN_FILENO, 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(ANSI_OSC "11;rgb:0/0/0" ANSI_ST)]; /* shortest possible reply */
         size_t buf_full = 0;
@@ -2359,7 +2357,7 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
         }
 
 finish:
-        RET_GATHER(r, RET_NERRNO(tcsetattr(STDIN_FILENO, TCSANOW, &old_termios)));
+        RET_GATHER(r, RET_NERRNO(tcsetattr(nonblock_input_fd, TCSANOW, &old_termios)));
         return r;
 }