Since v257, terminal_fix_size() is called during early boot via console_setup() → reset_dev_console_fd() to query terminal dimensions via ANSI escape sequences. This has caused intermittent boot hangs where the system gets stuck with a blinking cursor and requires a keypress to continue (see systemd/systemd#35499). The function tries CSI 18 first, then falls back to DSR if that fails. Previously, each method independently opened a non-blocking fd, disabled echo/icanon, ran its query, restored termios, and closed its fd. This created two problems: 1. Echo window between CSI 18 and DSR fallback: After CSI 18 times out and restores termios (re-enabling ECHO and ICANON), there is a brief window before DSR disables them again. If the terminal's CSI 18 response arrives during this window, it is echoed back to the terminal — where the terminal interprets \e[8;rows;cols t as a "resize text area" command — and the response bytes land in the canonical line buffer as stale input that can confuse the DSR response parser. 2. Cursor left at bottom-right on DSR timeout: The DSR method worked by sending two DSR queries — one to save the cursor position, then moving the cursor to (32766,32766) and sending another to read the clamped position. If neither response was received (timeout), the cursor restore was skipped (conditional on saved_row > 0), leaving the cursor at the bottom-right corner of the terminal. The subsequent terminal_reset_ansi_seq() then moved it to the beginning of the last line via \e[1G, making boot output appear at the bottom of the screen — giving the appearance of a hang even when the system was still booting. This commit fixes both issues: - terminal_fix_size() now opens the non-blocking fd and configures termios once for both query methods, so echo stays disabled for the entire CSI 18 → DSR fallback sequence with no gap. tcflush(TCIFLUSH) is called before each query to drain any stale input from the tty input queue. - The DSR method now uses DECSC (\e7) / DECRC (\e8) to save and restore the cursor position via hardware, instead of querying it with a separate DSR round-trip. All four sequences (DECSC, CUP to bottom-right, DSR query, DECRC) are sent in a single write, so the terminal processes DECRC and restores the cursor regardless of whether userspace ever reads the DSR response. This eliminates the cursor-at-bottom-right artifact on timeout and simplifies the read loop to only need a single DSR response instead of two. - The repeated setup boilerplate (dumb check, verify_same, fd_reopen, termios save/disable) is extracted into terminal_prepare_query(), shared by terminal_get_size_by_csi18(), terminal_get_size_by_dsr(), and terminal_fix_size(). Fixes: systemd/systemd#35499 Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
System and Service Manager
Details
Most documentation is available on systemd's web site.
Assorted, older, general information about systemd can be found in the systemd Wiki.
Information about build requirements is provided in the README file.
Consult our NEWS file for information about what's new in the most recent systemd versions.
Please see the Code Map for information about this repository's layout and content.
Please see the Hacking guide for information on how to hack on systemd and test your modifications.
Please see our Contribution Guidelines for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our Coding Style Guidelines.
If you are looking for support, please contact our mailing list, join our IRC channel #systemd on libera.chat or Matrix channel
Stable branches with backported patches are available in the stable repo.
We have a security bug bounty program sponsored by the Sovereign Tech Fund hosted on YesWeHack
Repositories with distribution packages built from git main are available on OBS, and also repositories with packages built from the latest stable release
