]> 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)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 25 Jun 2025 16:24:52 +0000 (01:24 +0900)
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

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

index 07e20cca8fd67e30047de684c98f9c9cabc73039..65bdd75f315a0de6bbb265f724d9d754ee8890fa 100644 (file)
@@ -122,18 +122,18 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool echo, 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)
@@ -323,7 +323,7 @@ int ask_string_full(
 
         struct termios new_termios = old_termios;
         termios_disable_echo(&new_termios);
-        if (tcsetattr(fd_input, TCSADRAIN, &new_termios) < 0)
+        if (tcsetattr(fd_input, TCSANOW, &new_termios) < 0)
                 return -errno;
 
         for (;;) {
@@ -446,7 +446,7 @@ int ask_string_full(
                 fflush(stdout);
         }
 
-        if (tcsetattr(fd_input, TCSADRAIN, &old_termios) < 0)
+        if (tcsetattr(fd_input, TCSANOW, &old_termios) < 0)
                 return -errno;
 
         if (!string) {
@@ -459,7 +459,7 @@ int ask_string_full(
         return 0;
 
 fail:
-        (void) tcsetattr(fd_input, TCSADRAIN, &old_termios);
+        (void) tcsetattr(fd_input, TCSANOW, &old_termios);
         return r;
 
 fallback:
@@ -2105,7 +2105,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);
@@ -2177,7 +2177,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;
 }
 
@@ -2302,7 +2302,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;
@@ -2414,7 +2414,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;
 }
 
@@ -2513,7 +2513,7 @@ int terminal_get_terminfo_by_dcs(int fd, char **ret_name) {
         struct termios new_termios = old_termios;
         termios_disable_echo(&new_termios);
 
-        if (tcsetattr(fd, TCSADRAIN, &new_termios) < 0)
+        if (tcsetattr(fd, TCSANOW, &new_termios) < 0)
                 return -errno;
 
         r = loop_write(fd, DCS_TERMINFO_Q, SIZE_MAX);
@@ -2568,7 +2568,7 @@ int terminal_get_terminfo_by_dcs(int fd, char **ret_name) {
 
 finish:
         /* We ignore failure here. We already got a reply and if cleanup fails, we can't help that. */
-        (void) tcsetattr(fd, TCSADRAIN, &old_termios);
+        (void) tcsetattr(fd, TCSANOW, &old_termios);
         return r;
 }
 
index 5b0cc14be81dca0d6124427d914a52cbec6af112..d8a0a88b43aa09ee54f5ac0159eed1bdc18e8dce 100644 (file)
@@ -566,7 +566,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;
 
@@ -783,7 +783,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;