]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
terminal-util: switch from TCSADRAIN to TCSANOW for all tcsetattr() calls
authorLennart Poettering <lennart@poettering.net>
Wed, 25 Jun 2025 09:49:47 +0000 (11:49 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 4 Aug 2025 18:50:36 +0000 (19:50 +0100)
TCSADRAIN means tcsetattr() will become blocking (waiting for ability to
write out queued bytes), which is problematic, if the referenced TTY is
dead for some reason.

Since all these calls just modify *input* parameters anyway (i.e. mostly
local echo, and canonical mode), forcing out queued output is kinda
pointless anyway, hence just don't do it: leave it in the queue and just
change the flags we want to change.

The tcsetattr(3) man page kinda hints that we want to use TCSANOW here,
because it documents for TCSADRAIN:

"This option should be used when changing parameters that affect
output."

Which one can read so that TCSADRAIN should not be used if it doesn't
affect output, which is the case here.

This probably fixes: #37854

(cherry picked from commit f789b17e87b675acf1638a1801d9b16a377742e0)

src/basic/terminal-util.c
src/shared/ask-password-api.c

index 7c1d2ad05001993de9242a630677d6b9fa861992..02df893b1965ec7ef9cb4a674e297607399169ab 100644 (file)
@@ -122,18 +122,18 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
                 new_termios.c_cc[VMIN] = 1;
                 new_termios.c_cc[VTIME] = 0;
 
-                if (tcsetattr(fd, TCSADRAIN, &new_termios) >= 0) {
+                if (tcsetattr(fd, TCSANOW, &new_termios) >= 0) {
                         char c;
 
                         if (t != USEC_INFINITY) {
                                 if (fd_wait_for_event(fd, POLLIN, t) <= 0) {
-                                        (void) tcsetattr(fd, TCSADRAIN, &old_termios);
+                                        (void) tcsetattr(fd, TCSANOW, &old_termios);
                                         return -ETIMEDOUT;
                                 }
                         }
 
                         r = safe_fgetc(f, &c);
-                        (void) tcsetattr(fd, TCSADRAIN, &old_termios);
+                        (void) tcsetattr(fd, TCSANOW, &old_termios);
                         if (r < 0)
                                 return r;
                         if (r == 0)
@@ -1915,7 +1915,7 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
         struct termios new_termios = old_termios;
         termios_disable_echo(&new_termios);
 
-        if (tcsetattr(STDIN_FILENO, TCSADRAIN, &new_termios) < 0)
+        if (tcsetattr(STDIN_FILENO, TCSANOW, &new_termios) < 0)
                 return -errno;
 
         r = loop_write(STDOUT_FILENO, ANSI_OSC "11;?" ANSI_ST, SIZE_MAX);
@@ -1979,7 +1979,7 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
         }
 
 finish:
-        RET_GATHER(r, RET_NERRNO(tcsetattr(STDIN_FILENO, TCSADRAIN, &old_termios)));
+        RET_GATHER(r, RET_NERRNO(tcsetattr(STDIN_FILENO, TCSANOW, &old_termios)));
         return r;
 }
 
@@ -2106,7 +2106,7 @@ int terminal_get_size_by_dsr(
         struct termios new_termios = old_termios;
         termios_disable_echo(&new_termios);
 
-        if (tcsetattr(input_fd, TCSADRAIN, &new_termios) < 0)
+        if (tcsetattr(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;
@@ -2209,7 +2209,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, TCSADRAIN, &old_termios)));
+        RET_GATHER(r, RET_NERRNO(tcsetattr(input_fd, TCSANOW, &old_termios)));
         return r;
 }
 
index 1c3ce4b5ed0a0ecceb7341d696a57627079c96e8..b63180e0c7cf9d3396c50be1debd66dd395f0866 100644 (file)
@@ -561,7 +561,7 @@ int ask_password_tty(
                 new_termios = old_termios;
                 termios_disable_echo(&new_termios);
 
-                r = RET_NERRNO(tcsetattr(ttyfd, TCSADRAIN, &new_termios));
+                r = RET_NERRNO(tcsetattr(ttyfd, TCSANOW, &new_termios));
                 if (r < 0)
                         goto finish;
 
@@ -758,7 +758,7 @@ skipped:
 finish:
         if (ttyfd >= 0 && reset_tty) {
                 (void) loop_write(ttyfd, "\n", 1);
-                (void) tcsetattr(ttyfd, TCSADRAIN, &old_termios);
+                (void) tcsetattr(ttyfd, TCSANOW, &old_termios);
         }
 
         return r;