diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 878c1ec06a..c81001ab67 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1900,6 +1900,7 @@ 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); @@ -1933,6 +1934,13 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret 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 = fd_reopen(STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (nonblock_input_fd < 0) + return nonblock_input_fd; + usec_t end = usec_add(now(CLOCK_MONOTONIC), 333 * USEC_PER_MSEC); char buf[STRLEN(ANSI_OSC "11;rgb:0/0/0" ANSI_ST)]; /* shortest possible reply */ size_t buf_full = 0; @@ -1941,13 +1949,12 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret for (bool first = true;; first = false) { if (buf_full == 0) { usec_t n = now(CLOCK_MONOTONIC); - if (n >= end) { r = -EOPNOTSUPP; goto finish; } - r = fd_wait_for_event(STDIN_FILENO, POLLIN, usec_sub_unsigned(end, n)); + r = fd_wait_for_event(nonblock_input_fd, POLLIN, usec_sub_unsigned(end, n)); if (r < 0) goto finish; if (r == 0) { @@ -1958,8 +1965,10 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret /* On the first try, read multiple characters, i.e. the shortest valid * reply. Afterwards read byte-wise, since we don't want to read too much, and * unnecessarily drop too many characters from the input queue. */ - ssize_t l = read(STDIN_FILENO, buf, first ? sizeof(buf) : 1); + ssize_t l = read(nonblock_input_fd, buf, first ? sizeof(buf) : 1); if (l < 0) { + if (errno == EAGAIN) + continue; r = -errno; goto finish; } @@ -2083,6 +2092,8 @@ int terminal_get_size_by_dsr( unsigned *ret_rows, unsigned *ret_columns) { + _cleanup_close_ int nonblock_input_fd = -EBADF; + assert(input_fd >= 0); assert(output_fd >= 0); @@ -2130,6 +2141,13 @@ 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 = fd_reopen(input_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (nonblock_input_fd < 0) + return nonblock_input_fd; + usec_t end = usec_add(now(CLOCK_MONOTONIC), 333 * USEC_PER_MSEC); char buf[STRLEN("\x1B[1;1R")]; /* The shortest valid reply possible */ size_t buf_full = 0; @@ -2138,13 +2156,12 @@ int terminal_get_size_by_dsr( for (bool first = true;; first = false) { if (buf_full == 0) { usec_t n = now(CLOCK_MONOTONIC); - if (n >= end) { r = -EOPNOTSUPP; goto finish; } - r = fd_wait_for_event(input_fd, POLLIN, usec_sub_unsigned(end, n)); + r = fd_wait_for_event(nonblock_input_fd, POLLIN, usec_sub_unsigned(end, n)); if (r < 0) goto finish; if (r == 0) { @@ -2155,8 +2172,11 @@ int terminal_get_size_by_dsr( /* On the first try, read multiple characters, i.e. the shortest valid * reply. Afterwards read byte-wise, since we don't want to read too much, and * unnecessarily drop too many characters from the input queue. */ - ssize_t l = read(input_fd, buf, first ? sizeof(buf) : 1); + ssize_t l = read(nonblock_input_fd, buf, first ? sizeof(buf) : 1); if (l < 0) { + if (errno == EAGAIN) + continue; + r = -errno; goto finish; }