basic/terminal-util: use non-blocking writes when sending ANSI sequences in terminal_get_size()
terminal_get_size() writes ANSI escape sequences (CSI 18 and DSR queries) to the output fd to determine terminal dimensions. This is called during early boot via reset_dev_console_fd() and from service execution contexts via exec_context_apply_tty_size(). Previously, these writes used loop_write() on a blocking fd, which could block indefinitely if the terminal is not consuming data — for example on a serial console with flow control asserted, or a disconnected terminal. This is the same problem that was solved for terminal_reset_ansi_seq() in systemd/systemd#32369 by temporarily setting the fd to non-blocking mode with a write timeout. Apply the same pattern here: set the output fd to non-blocking in terminal_get_size() before issuing the queries, and restore blocking mode afterward. Change the loop_write() calls in terminal_query_size_by_dsr() and terminal_query_size_by_csi18() to loop_write_full() with a 100ms timeout so writes fail gracefully instead of hanging. Also introduce the CONSOLE_ANSI_SEQUENCE_TIMEOUT_USEC constant for all timeouts used across all ANSI sequence writes and reads (vt_disallocate(), terminal_reset_ansi_seq(), and the two size query functions). 333ms is now used for all timeouts in terminal-util.c. Also introduce a cleanup function for resetting a fd back to blocking mode after it was made non-blocking.
This commit is contained in:
committed by
Daan De Meyer
parent
e98a26ddc0
commit
ba10d789a8
@@ -112,6 +112,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
|
||||
int fd_nonblock(int fd, bool nonblock);
|
||||
int stdio_disable_nonblock(void);
|
||||
|
||||
void nonblock_resetp(int *fd);
|
||||
|
||||
int fd_cloexec(int fd, bool cloexec);
|
||||
int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user