From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Nov 2025 13:33:26 +0000 (+0100) Subject: basic/terminal-util: operate on one fd in get_default_background_color() X-Git-Tag: v259-rc2~24^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46f6742911ba70ad19cc94da241dc4ff7b1c7489;p=thirdparty%2Fsystemd.git basic/terminal-util: operate on one fd in get_default_background_color() 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. --- diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index f17352b41b8..337c35a1934 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -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; }